home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 March: Reference Library / Dev.CD Mar 96 RL / Dev.CD Mar 96 RL.toast / Technical Documentation / develop / develop Issue 20 / develop Issue 20 references / Newton Q&A / Q&A NewtonScript / Q&A NewtonScript
Encoding:
Text File  |  1994-07-12  |  120.3 KB  |  129 lines  |  [ONLN/HLX2]

  1. NEWTONSCRIPT PROGRAMMING LANGUAGE
  2. © Copyright 1993-94 Apple Computer, Inc, All Rights Reserved
  3. _____________________________________________
  4.     
  5. Introduction
  6. This document addresses NewtonScript Programming Language  issues that are not available in the currently printed documentation . Please note that this information is subject to change as the Newton technology and development environment evolve.
  7. TABLE OF CONTENTS:
  8. • NEW: NewtonScript Object Sizes (6/30/94)
  9. • Play Catch - NewtonScript Exceptions (Obsoleted by NS Guide 1.0
  10.     Final Documentation)
  11. NewtonScript Q&As
  12. • Garbage Collection (10/15/93) (obsoleted by NS Guide 1.0 Final Documentation)
  13. • Order of Slots in Frames (9/15/93) 
  14. • Structured Literals (9/15/93) 
  15. • Passing Arguments (9/15/93) 
  16. • Slot (Variable) Lookup (9/15/93) 
  17. • Testing the Existence of a Slot (Variable) (9/15/93) (Obsoleted by NS 1.0 Final
  18.    Documentation)
  19. • Calling Methods Out Of Slot Context (9/15/93) (Obsoleted by NS Guide 1.0 Final 
  20.    Documentation)
  21. • Inherited (10/13/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  22. • Deeply (foreach deeply in...) (10/13/93)(Obsoleted by NS Guide 1.0 Final 
  23.    Documentation)
  24. • Compile Function (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  25. • Function Definitions (10/9/93)
  26. • Closures and Perform (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  27. • Symbol Hacking (11/11/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  28. • Literals and Runtime (11/11/93)
  29. • Missing SemiColons cause Weird Errors (12/11/93) (Obsoleted by NS Guide 1.0 
  30.    Final Documentation)
  31. • Classical OOP programming ala NewtonScript (12/17/93) (Obsoleted by NS Guide 1.0 
  32.    Final Documentation)
  33. • Only 7-Bit ASCII In NewtonScript Symbols (1/26/94) (Obsoleted by NS Guide 1.0 
  34.    Final Documentation)
  35. • Nested IF Statements, Constant Condition Problems (6/9/94)
  36. • NEW: How to Avoid _parent Problems (6/28/94)
  37. _____________________________________________________________________________    
  38. NEW: NewtonScript Object Sizes (6/30/94)
  39. Generic
  40. The Newtonscript Objects are the objects that either reside in the read-write memory,  pseudo-ROM memory or inside the package or ROM. These objects are aligned to 8-byte boundaries. This alignment causes a very small amount of fragmentation (usually under 2%) so this issue could be ignored. 
  41. Immediates
  42. The Newton Object System has four built-in primitive classes that describe an object's basic type: Immediates, binaries, arrays and frames. In the case of an Immediates (integers, character, boolean and so on)  we are dealing with a 30+2 bit object.  
  43. In the case of binaries, arrays and frames we are also dealing with objects containing a so called Object Header.
  44. Object Header
  45. Every object has a 12-byte header that contains information concerning size, flags, class, lock count and so on. This information is implementation specific.
  46. Strings
  47. A string object contains a 12 byte header plus the Unicode strings plus a null termination character. Note that Unicode characters are two-byte values. Here's an example:
  48. "Hello World!"
  49. This string contains 12 characters, in other words it has 24  bytes. In addition we have a null termination character (24  + 2 bytes) and an object header  (24 + 2 + 12 bytes), all in all the object is 38 bytes big. Note that we have not taken into account any possible savings if the string was compressed (using the NTK compression flags).
  50. Binary Objects
  51. A binary object contains  a 12 byte header plus the size of the actual data.
  52. Array Objects
  53. Array objects have an object header (12 bytes) and additional four bytes per element. In addition you need to calculate the amount of data stored in the arrays as well (references) if you want to calculate the total amount.
  54. Here's an example:
  55. ["Hello World!", "foo"]
  56. We have a header (12 bytes) plus four bytes per element (12  + (2 * 4)  bytes). In addition we have string objects that we refer to  (12 + (2*4) + 38 + 20 bytes), all in all 78 bytes. Again we have not taken into account savings concerning compression. Note that the string objects could be referred by other arrays and frames as well, so if we want to take this into account we should make sure the string is counted only once per package.
  57. Frame Objects
  58. We have two kinds of frames, frames that don't have a shared map object, and frames who do have a shared map object. We take the simple case first (no shared map object).
  59. An array object map is an array of symbol pointers and one additional slot. The actual frame is two arrays, one contains the slot names, and the other contains the actual slot entry.
  60. The map is 16 bytes, if we add the object header to this the basic header size of a frame is 28 bytes.  If we want to add the size taken by slot entries we multiply N slots with 8 (two array entries). Here's an example:
  61. {Slot1: 42, Slot2: "hello"}
  62. We have a header of 28 bytes, in addition we have two slots (28 + (2 * 8)), all in all  48 bytes. Once again we didn't calculate the actual slot entry objects.
  63. In the case of a frame with a shared map multiple similar frames (look the same) could share the one and only map. This will save space, reducing the marginal overhead per frame to the same as an array with the same amount of slots. In addition we need to take into account the amortized map size that multiple frames share. In other words the magic formula this time is 12 bytes for the header plus  4 times the amount of slots plus the amortized map size.
  64. Here's an example of a frame with a shared map:
  65. {Slot1: 42, Slot2: "hello"}
  66. We have a header of 12 bytes, in addition we have two slots (2 * 4), and additional 16 bytes for the size of a map with no slots, all in all 36 bytes. We should also take into account the shared map, in the worst case there's only one of these frame objects, in other words we have additional 16 bytes.
  67. When do we create objects with a shared map?
  68. 1. When we clone the system will make sure that the cloned object uses the same map. A trick to make use of this is to create a common template frame, and when we need to create additional frames we clone this template frame over and over.
  69. 2. The system will make sure that the frame uses a shared map if the frame is created by a a frame constructor expression in most cases a function that returns a frame. This is the reason we use RelBounds when we create the viewBounds frame, in other words there's just one single viewBounds map in the system, and it's stored inside the ROM.
  70. Note again that these figures are for objects in their runtime state, ready for fast access. Objects in transit or in storage (packages) are compressed into smaller stream formats. These figures are neither true for flattened objects that are sent over a comms endpoint, neither true for objects stored in soups.
  71. Symbols
  72. Asymbol is a frame with two slots, one pointing to a string containing the name, the other pointing to the next symbol in an internal  hash table.  Symbols share one map, so each symbol occupies 12+2*4 = 20 (round to 24) bytes for the frame and 12+length (rounded) bytes for the name, for a total of 36+length bytes.
  73. A symbol is a binary object that contains a four-byte hash value and the name is a null terminated ASCII character . Each symbol is 12 (header) + 4 (hash value_) + length of object + 1 bytes (null termination ASCII char).
  74. PLAY CATCH - NEWTONSCRIPT EXCEPTIONS
  75. (9/15/93) (Obsoleted by NS Guide 1.0 final docs)
  76. Introduction
  77. The NewtonScript exception system provides a structured way for a module to report a failure to another module.  It communicates the type of the failure, and allows (optionally) transmission of data that may explain the reason for the failure.  The NewtonScript implemention uses the exception system to report errors (for example, errors in an application, failures due to lack of resources, or internal errors).  Developers can use the exception system to communicate errors between different modules in an application.
  78. Basic Syntax
  79. The Exception handling is based on a try block, and if an exception is thrown from somewhere, the code should catch this with a special onException block.
  80. Try Statements
  81. The general format of the try statement is:
  82. try
  83.     <statement list>
  84. onexception <exception symbol> do
  85.     <statement>
  86. onexception <exception symbol> do
  87.     <statement>
  88. ...
  89. An example of this might be:
  90. try
  91. begin
  92.     // create entries and store them to soups
  93. end
  94. onexception |ext.ex.store.err| do
  95. begin
  96.     // problems with the store, most likely not enough memory
  97.     // do something
  98. end
  99. The <exception symbol>s  must be single part exception symbols. Details about exception symbols — that is,  what multiple parts mean —  are discussed below.
  100. One or more onexception clauses are allowed. The try statement executes <statement list>. If no exceptions are thrown in the process, then the value of the try statement is the value of the last statement in <statement list> and the onexception clauses are never executed.
  101. If during execution of <statement list> an exception is thrown, then the execution of <statement list> stops and control is transferred to one of the onexception clauses. When an exception, X, is raised, the onexception clauses of the try statement are examined in order. The first clause whose <exception symbol> is a prefix of any of X's parts is executed and its <statement> value becomes the value of the try statement.
  102. If no onexception clause matches the exception, then the exception is passed to the next enclosing try statement for processing. In a Newton application, the exception will ultimately be handled by the view system (putting up an error dialog box) if your application doesn't catch it.
  103. NOTE:  It is important that the search for a matching onexception clause uses dynamic scoping, not lexical scoping.
  104. Since all exceptions have an evt.ex part, an exception clause with evt.ex as its symbol will catch any exception. (See the following section for a description of "parts".) If your try statement has an evt.ex clause,  it should be last, since onexception clauses occuring after it will never be executed. In general, you should order your onexception clauses from most specific to least specific.
  105. Exception Symbols
  106. Exceptions have names which are symbols.  These symbols have a particular format which must be adhered to.  An exception name consists of one or more parts separated by semi-colons.  Each part is a structured name beginning with evt.ex. 
  107. A  few facts about exception symbols:
  108.     • They can have as many as 127 characters.
  109.     • They can contain periods, so the symbols must be enclosed in vertical bars (|'s)
  110.     • They can have multiple parts, separated by semi-colons.
  111.     • They must have a part starting with evt.ex.
  112. The simplest possible exception symbol is |evt.ex|. An example of an exception symbol with two parts would be '|evt.ex;type.ref|.  Some more examples: '|evt.ex.div0|, '|evt.ex.fr.intrp;type.ref.frame|.
  113. Exception Frames
  114. Associated with every exception is an exception frame. When handling an exception you can get this frame using the global function, CurrentException(). An exception frame always has a name slot which contains the exception symbol. It will contain one other slot whose name and contents depend on the type of exception as follows: (this info is summarized on the NS Quick Ref Card)
  115. • if  type.ref is a prefix in the exception symbol, then the other slot will be called data and can contain anything.
  116. |evt.ex;type.ref|: {name: <string>, data: <frame>}
  117. Ex: {name: "the llama exception", data : {type: 'inka, size: 42, weight: 177}}
  118. • if evt.ex.msg is a prefix in the exception symbol, then the other slot will be called message and contain a string
  119. |evt.ex.msg|: {name: <string>, message: <string>}
  120. Ex: {name: "Ho ho exception", message: "You have a serious problem, mate"}
  121. • otherwise, the other slot will be called error and will contain an integer (error code)
  122. |evt.ex|: {name: <string>, error: <integer>}
  123. Ex: {:name: "Hi Ho exception", error: -48666}
  124. Here are examples of exception frames from real life:
  125. • Example A,  division by zero:
  126. {name: |evt.ex.div0|, error: 1764744}
  127. If you want to catch division by zero errors, here's the trick:
  128. try
  129.     5/0
  130. onexception |evt.ex| do
  131.     CurrentException();
  132. • Example B, undefined variable:
  133. {name: |evt.ex.fr.interp; type.ref.frame|, data: {error:-48807, symbol: foo}}
  134. How to Raise Gentle Exceptions
  135. You can throw an exception using the global function, Throw(<exception symbol>, <exception data>). The value you pass for <exception data> is put into the "other" slot of the exception frame. Make sure it is the correct type (as per the above rules) or your  call to Throw will raise another exception.
  136. If the code block has more than one try statement in effect at one time, you can pass control to the next enclosing try statement using the Rethrow  function. 
  137. Here are examples of the three different ways to create and throw exceptions. Note that you need to send an exception symbol ('):
  138. Throw('|evt.ex.foo|, 99);
  139. Throw('|evt.ex.msg|, "string");
  140. Throw('|evt.ex;type.ref.something|, ["a", "b", "c"])
  141. Default Exception Handling
  142. Unfortunately, there is currently no general way for your application to specify a default exception handler, for example, viewExceptionScript. This means you need to use try statements wherever you want to catch exceptions.
  143. Examples
  144. Here's some code  to test out the exception system. This tries various cases and is designed to print no output, assuming  the exception system works as advertised. However,  the NTK Inspector prints out every exception that is thrown, whether it's handled or not. Expect to see output; however, none of thePrint("*error?*) statements should execute.
  145. //simple cases & a nested block
  146. try
  147.     begin
  148.     
  149.         try
  150.             Throw('|evt.ex;type.ref;foo|,"dsafsda");
  151.             Print("*error*1");
  152.         onexception |foo| do
  153.             begin
  154.                 //Exception handled quietly
  155.              end;
  156.              
  157.         try
  158.             Throw('|evt.ex;type.ref;foo|,"dsafsda");
  159.             Print("*error*2");
  160.         onexception |type.ref| do
  161.             begin
  162.                 //Exception handled quietly
  163.              end;
  164.     
  165.       //outer block should catch this one
  166.         Throw('|evt.ex.foobar|,42);
  167.                  
  168.       Print("*error*3");
  169.     end
  170. onexception |evt.ex| do
  171.     if CurrentException().error <> 42 then
  172.         begin
  173.             Print("*error*4");
  174.             Print(CurrentException())
  175.         end;
  176. //try out rethrow()
  177. try
  178.     begin
  179.         
  180.         try
  181.             Throw('|evt.ex|,42);
  182.             Print("*error*5");
  183.         onexception |evt.ex| do
  184.             begin
  185.          //outer block should catch this one
  186.                 Rethrow();
  187.              end;
  188.     
  189.     Print("*error*6");
  190.              
  191.     end
  192. onexception |evt.ex| do
  193.     if CurrentException().error <> 42 then
  194.         begin
  195.             Print("*error*7");
  196.             Print(CurrentException())
  197.         end;
  198. //try it out with fn calls
  199. try
  200.     begin
  201.         
  202.         call func()
  203.             begin
  204.                 try
  205.                     call func(esym) Throw(esym,42) with ('|evt.ex|);
  206.                     Print("*error*8");
  207.                 onexception |type.ref| do
  208.                     begin
  209.                  //outer block should catch this one
  210.                         Rethrow();
  211.                      end;
  212.             end
  213.         with ();
  214.         
  215.         Print("*error*9");
  216.              
  217.     end
  218. onexception |evt.ex| do
  219.     if CurrentException().error <> 42 then
  220.         begin
  221.             Print("*error*10");
  222.             Print(CurrentException())
  223.         end;
  224. Print("no news, is good news");
  225. _____________________________________________________________________________    
  226. NewtonScript Q&As
  227.     ___________________________________________
  228. Garbage Collection (10/15/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  229. In NewtonScript, the run-time module, not the programmer, is responsible for allocating storage for objects and for reclaiming the storage of objects that are no longer used. Garbage collection is carried out by the basic object system, so it’s not technically NewtonScript that does it.  The storage taken up by an object will be freed sometime after the last reference to that object goes away.
  230. One of the many benefits of garbage collection is that the programmer has to think about freeing objects only  in a small number of important places, as opposed to dealing with the constant background worry that objects must be freed. Wth automatic garbage collection you only need to consider disposing objects in rare cases.
  231. One place where you should think about it is when you close an application; here you want to free as much storage as possible. You do this by either removing slots  or by setting slots to nil in the application's context frame.  Setting the value of all slots and variables referring to a particular object to nil allows the Garbage Collector to destroy the object.
  232. Within the Newton operating system, automatic garbage collection is triggered every time the system runs out of memory. There's not really any reason to invoke garbage collection manually. However, if you must do so, you can call the global NewtonScript function GC. Consult the Newton Programmer’s Guide to find out more about the GC function.
  233.     ___________________________________________
  234. Order of Slots in Frames (9/15/93) 
  235. Q:     The description of the foreach function in the manual might be taken as a hint that slots in frames are ordered.  Does slot or array order imply anything about layout of data in memory (as with C structs?)
  236. A:     Slots are not ordered, nor have we seen any performance gains from ordering slots for particular sequences or search criteria. Don’t count on their being in any particular order, nor on data structures in memory being ordered with any regard to the placement of slots (as in the ANSI Common LISP object extension CLOS). 
  237. Q:    Where is a newly-defined slot placed in a frame? at the end?
  238. A:    Because slots are unordered, the location of a new slot cannot be predetermined.
  239.     ___________________________________________
  240. Structured Literals (9/15/93) 
  241. Q:     Is it really dangerous to assign a string literal to a variable, as in the following example?
  242.     s := "abc";
  243. A:     That depends on what you're going to do with s. If you're
  244.     going to modify it, then yes, it's dangerous. In that case, you
  245.     should use 
  246.     s := Clone("abc");
  247.     In general you should treat string literals in NewtonScript
  248.     as read-only (just as you should in ANSI C). String literals might
  249.     reside in read-only memory or share storage with other literals.
  250.     The same warning applies to quoted array and frame literals, as in the following example:
  251.      '[1,2,3] or '{one: 1, two: 2, three: 3}
  252.     Here are some rules regarding string literals and quoted array/frame literals:
  253.     - Treat them as read only. Use clones when necessary.
  254.  
  255.     - Realize that they always represent the same object.   In the example below,
  256.     func foo() begin "abc"
  257.     end; 
  258.      - always returns exactly the same string - not different,
  259.     equivalent strings.
  260.     - In your code, an unquoted array or frame literal will generate a
  261.     new array or frame each time it is evaluated. So it’s acceptable for a
  262.     function to return [1,2,3] or {one: 1,two: 2,three: 3} as long as
  263.     they're not quoted.
  264.     ___________________________________________
  265. Passing Arguments (9/15/93) 
  266. Q:     Is NewtonScript call-by-reference or call-by-value?
  267. A:     A seemingly simple question. The short answer is “call-by-value,” the litmus test being that
  268.      func foo(x) x := 1;
  269.     does not affect the argument passed to it. However, this is not meant to imply that NewtonScript functions can never make changes to their arguments. If the argument has structure—for example, if it’s an array, frame, or string—then changes to the internal structure are persistent. Consider the following code fragments:
  270.      func foo(x) x[0] := 1; 
  271.     // changes the 1st element of array arguments
  272.  
  273.     func foo(x) x.slot1 := 1; 
  274.     // changes the slot1 slot of frame arguments
  275.     Depending on what you’re used to, this example might be confusing because the concepts of call-by-reference, call-by-value are mixed, and copying arguments are intertwined (and often misunderstood.) The following discussion of this terminology with respect to other languages may help clarify the differences.
  276.     Pascal - Supports both call-by-reference (VAR parameters) or call-by-value (the default). When array or record arguments use call-by-value, copies of the arrays/records are made and passed in. To Pascal programmers, NewtonScript may seem to pass arrays and frames as VAR parameters.
  277.     C - Only supports call-by-value. Struct (not struct*) arguments are
  278.     passed as values; that is, a copy of the struct is passed. However, array arguments pass in the address of the first element of the array. Thus, C programmers will find the array arguments to be treated normally.
  279.     LISP - Only supports call-by-value. Copies are not made of structured
  280.     arguments (lists, structures, arrays, objects,...) Argument passing in Newton Script works just like it does in LISP.
  281.     ________________________________________
  282. Slot (Variable) Lookup (9/15/93) 
  283. Q:     What differences are there among the various ways to access a slot?
  284. A:    The means by which you access a slot specifies the search path and inheritance mechanisms used to locate it. Each of the five ways to access a slot is described below.
  285.     •Specifying the slot name only
  286.     If you specify only the name of the slot, as in the example
  287.     theSlot
  288.     the search begins in the current function frame with lexically-visible variables, followed by slot names. In other words, if the currently-executing function has a local variable named theSlot, it is found before a local variable named theSlot in the enclosing function, and so on. Similarly, any of those variables are found (in scope order) before an actual slot named theSlot is found. If a variable named theSlot is not found, global variables are searched next. If a global variable is not found, the current receiver is searched for a slot named theSlot.
  289.     If the slot is not found in the receiver of the message, the remaining frames are searched in order of prototype and parent inheritance. An exception is thrown if you try to access a slot that can't be found.  If you do an assignment operation using an undeclared slot, the slot is created if you place the self. prefix in front of the slot name; if you do the operation without the self. prefix you will get a local variable.
  290.     •Using the dot (.) operator
  291.     If you use the dot operator to specify the frame and the slot,  as in the example
  292.     myframe.myslot
  293.     the search begins in the specified frame.  If the slot is not found in the specified frame, the remaining frames are searched in order of prototype inheritance.  Parent inheritance paths are not searched. If the slot does not exist, the system returns NIL.
  294.  
  295.     •Using the GetSlot function
  296.     If you call 
  297.     GetSlot(frame, slot) 
  298.     only the specified frame is searched for the specified slot. Inheritance paths are not searched.
  299.     •Using the GetVariable function
  300.     If you call 
  301.     GetVariable(frame, slot) 
  302.     the search begins in the specified frame.  If the slot is not found in the current frame, the remaining frames are searched in order of prototype and parent inheritance.
  303.     •GetVar will be removed from the language
  304. You can usually simulate GetVar using GetVariable(self,slot). The difference will be that local variables will not be found - only slots.
  305. If you use GetVar you may find that is not available in future products, in which case your code will throw an exception; or  GetVar may work differently not finding local variables anymore, in which case your code may subtly break. DTS advises against using GetVar.
  306.     ___________________________________________
  307. Testing the Existence of a Slot (Variable) (9/15/93) (Obsoleted by NS 1.0 Final Documentation).
  308. Q:     What differences are there among the various ways to determine whether a slot exists in a frame?
  309. A:    The means by which you test for a slot's existence specifies the search path and kinds of inheritance used to discover it. The following examples describe three ways to discover the existence of a slot in a frame.
  310.     • Using the exists operator
  311.     The exists operator follows the same rules as the expression to which it is applied. For example, if you use this operator to test a slot access expression, as in the example
  312.     myframe.myslot exists 
  313.     the search begins in the specified frame.  If the slot is not found in the current frame, the remaining frames are searched in order of prototype inheritance only. Parent inheritance paths are not searched.
  314.     However, when using the exists operator to check whether an identifier exists, as in the example
  315.     myvar exists 
  316.     both prototype and parent inheritance paths are searched.
  317.     • Using the HasSlot function
  318.     If you call
  319.     HasSlot(frame, slot)
  320.     only the specified frame is searched for the specified slot. Inheritance paths are not searched.
  321.     • Using the HasVariable function
  322.     If you call
  323.     HasVariable(frame, slot)
  324.     the search begins in the current frame. If the slot is not found in the current frame, the remaining frames are searched in order of prototype and parent inheritance.
  325.     ___________________________________________
  326. Calling Methods Out Of Slot Context (9/15/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  327. Q:     I'm trying to pull a method out of a slot and call it. Unfortunately, the functions apply and call both seem to set self to {}. Is there another way?
  328. A:     The global function Perform(frame, message, paramaterArray) does what you want, except that the method needs to be in a slot in the current frame if you really want to preserve the value of self.
  329.     ___________________________________________
  330. Inherited (10/13/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  331. Q:     What is the function of "inherited:" and "inherited:?"
  332. A:  In NewtonScript, the inherited:X() message send specifies a NewtonScript function call on the function X, where X is found UP the inheritance chain starting from the caller's _proto. In other words, lookup for that method ONLY starts up the caller's _proto chain, NOT in  "self" (the currently executing frame). The conditional message send (:?), with inherited specified, operates almost exactly the same  except that no error results if the given method (function) is NOT found. The conditional message send (:?), with inherited specified, is helpful in complex heirarchies because you can use it without  worrying about whether any such method was ever implemented higher up in the inheritance chain.
  333.     ___________________________________________
  334. Deeply (foreach deeply in...) (10/13/93)(Obsoleted by NS Guide 1.0 Final Documentation)
  335.     
  336. Q:     What is the difference between "foreach" and "foreach deeply in"?
  337. A:  'Deeply' specifies that only the slots/elements of the current frame/array are listed, except that if passed a frame, slots of ancestors up the _proto chain are considered elements of the current frame. 
  338.     Here is some Inspector code to illustrate the difference between the two:
  339.     //oo DEFINITIONS
  340.     normallist := func (param) 
  341.        begin
  342.           local tempItem;
  343.           foreach tempItem in param 
  344.                   collect tempItem;
  345.        end;
  346.     deeplylist := func (param) 
  347.        begin
  348.           local tempItem;
  349.           foreach tempItem deeply in param 
  350.                   collect tempItem;
  351.        end;
  352.     //oo SAMPLE DATA
  353.     x := {one: 1, two: 2, three: 3};
  354.     y:= {four: 4, five: 5, combo: x};
  355.     z:= {six: 6, _proto: y};
  356.     complex := {a: "first string", b: ["array1", "array2", 
  357.         {_proto: x}], c: 3.1415926};
  358.          
  359.     //oo TESTS
  360.     :normallist(x)          // same
  361.     #4413441  [1, 2, 3]
  362.     :deeplylist(x)
  363.     #44137D9  [1, 2, 3]
  364.     :normallist(y)          // same
  365.     #4413A11  [4, 
  366.            5, 
  367.            {One: 1, 
  368.             two: 2, 
  369.             three: 3}]
  370.     :deeplylist(y)
  371.     #4413C49  [4, 
  372.            5, 
  373.            {One: 1, 
  374.             two: 2, 
  375.             three: 3}]
  376.                         // For z, the answer is different. 
  377.                         // the deeply version travels proto chains!
  378.     :normallist(z)
  379.     #4416E29  [6, 
  380.            {four: 4, 
  381.             five: 5, 
  382.             combo: {#4415D79}}]  
  383.     :deeplylist(z)
  384.     #4416FE1  [6, 
  385.            4, 
  386.            5, 
  387.            {One: 1, 
  388.             two: 2, 
  389.             three: 3}]
  390.                  // for this complex frame, the answers are the same 
  391.                  // because there is no _proto slot in the *MAIN* frame 
  392.                  // hence there is nowhere to go deeply into.
  393.     :normallist(complex)
  394.     #4418741  ["first string", 
  395.            ["array1", "array2", {#44183B9}], 
  396.            3.14159]
  397.     :deeplylist(complex)
  398.     #4418AC1  ["first string", 
  399.            ["array1", "array2", {#44183B9}], 
  400.            3.14159]
  401.     ___________________________________________
  402. Compile Function (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  403. Q:     I need the ability to download the validtest and endtest functions to the Newton for searches.  I do not see how I can convert the incoming textual representation of the function to code to execute.  How could I do this?
  404. A:    You could use the special compile function in NewtonScript. Here's an example of how to use compile:
  405.     begin
  406.           local x;
  407.           // Set x to be a function that returns the new function.
  408.           x := Compile("Print(\"Hello\")");
  409.             // Now call the actual compiled function.
  410.           call x with ();
  411.           // At this point, "Hello" will have been printed to the inspector...
  412.     end;
  413.     Note that compile returns a function taking no arguments whose body is the string passed to compile.  If you need to create a function taking arguments, you can create a function with Compile whose return value is a function that takes arguments, like this:
  414. f := call Compile("func(x) x*x") with ();
  415. call f with (10);  // prints 100.
  416.     ___________________________________________
  417. Function Definitions (10/9/93)
  418. Q:    Is it "safer" to use a return statement at the end of a function or is it just a style issue?
  419. A:    All functions return the last value in the function body. This means that you have a choice of explicitly writing a return statement, or assuming that the code reader knows that the last statement is automatically returned.
  420.     One might argue that a return statement should always be used. However there are cases where the code looks prettier with no return statement, and the return statement does generate code. Compare the following two examples:
  421.     begin
  422.         ...
  423.         if expr then "" else text
  424.     end
  425.     begin
  426.         if expr then
  427.             return ""
  428.         else
  429.             return text
  430.     end
  431.     Additionally, in the current NewtonScript compiler, an extra byte or two is used for the return statement, but in most cases it will make no apparent difference in speed.
  432.     ___________________________________________
  433. Closures and Perform (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  434. Q:     The NewtonScript manual indicates that the receiver during a call is the receiver that made the call. For example, the code
  435.  
  436.         a := {
  437.         id: "a",
  438.         foo: func() Print(id),
  439.     };
  440.  
  441.     b := {
  442.         id: "b",
  443.         bar: func() call a.foo with (),
  444.     };
  445.  
  446.     b:bar();
  447.  
  448.     should print "b".
  449.  
  450.     When I run this in an Inspector, however, it appears that the receiver during the execution of foo() is the top level frame in which a (and b) is defined.  How is the receiver actually determined?  Is it always the top level of the Inspector?
  451.  
  452. A:     What you really create is a closure, which is the executable code bound up with the dynamic and lexical environments at the time the function was created.  That is, whatever self evaluated to when the function was compiled is what it will evaluate to when it's called.
  453.     The Perform  call, or message-passing does change the closure's dynamic environment (self) to the frame that was specified by the message pass or Perform call.
  454.     To do what you seem to be attempting, you could try this:
  455.     a := {
  456.         id: "a",
  457.        foo: func() Print(id)};
  458.     b := {
  459.         id: "b",
  460.         bar: func() begin self.temp := a.foo; :temp() end}; 
  461.     b:bar();
  462.     Instead of :temp() above, you could have used Perform(self, 'temp, []);  Perform is handy when you don't know at compile time which message you need to pass. For example, you can write Perform(self, jumpTable[i], []); where jumpTable contains an array of symbols representing methods. Perform takes a frame, a message and an array of message parameters.
  463.     ___________________________________________
  464. Symbol Hacking (11/11/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  465. Q:    I would like to be able to build frames dynamically and have my application create the name of the slot in the frame dynamically as well.  For instance, something like this:
  466.     MyFrame:= {}; tSlotName := "Slot_1";
  467.     
  468.     At this point is there a way to then create this ?:
  469.     MyFrame.Slot_1
  470. A:    There is a function called Intern, that takes a string and makes a symbol. There is also a mechanism called path expressions (see the NewtonScript manual), that allows you to specify an expression or variable to evaluate, in order to get the slot name. You can use these things to access the slots you want:
  471.     MyFrame := {x: 4} ;            // MyFrame -->{x: 4}
  472.     theXSlotString := "x" ;
  473.     MyFrame.(Intern(theXSlotString)) := 6 
  474.                          // MyFrame --> {x: 6}
  475.     tSlotName := "Slot_1" ;     // the following code creats a
  476.                         // slot called Slot_1 in MyFrame and 
  477.                         // assigns it the number 7.     MyFrame.(Intern(tSlotName)) := 7 ;      
  478.                         // MyFrame --? {x: 6, Slot_1: 7} 
  479. Q:    Is there a way to look for a slot programmatically starting with a slot name string?
  480. A:    Here's the code which can do this:
  481.     if MyFrame.(Intern(slotToFind)) exists then 
  482.           x := MyFrame.(Intern(slotToFind)) ;  // use the slot
  483.     
  484.     ___________________________________________
  485. Literals and run time (11/11/93)
  486. Q:    Is the literals slot really needed during run time? I noticed that I could figure out quite a lot about how my functions work from the literals used (examining the literals slot). I would rather not make it easy for others to reverse engineer certain routines.
  487. A:    The literals slot is indeed needed during run time (in the current implementation of NewtonScript) The interpreter is using it at run time. Here's an example:
  488.     f := func() "abc";
  489.     #4409CB9  <CodeBlock, 0 args #4409CB9>
  490.     f.literals
  491.     #4409B61  [literals: "abc"]
  492.     f.literals[0] := {foo: 'bar}
  493.     #440A1D1  {foo: bar}
  494.     call f with ()
  495.     #440A1D1  {foo: bar}
  496.     Don't assume anything about the implementation of the literals slot in future Newton system software.
  497.     ___________________________________________
  498. Missing Semicolons cause Weird Errors (12/11/93) (Obsoleted by NS Guide 1.0 Final Documentation)
  499. As with Pascal, semicolons are statement separators, not terminators. If you forget to add a semicolon at the end of the Newtonscript statement, the interpreter will try to interpret a larger statement than intended, causing strange error reports.
  500. The following is an example of such a case.
  501. You are getting an "expected array, frame, or binary but got 8" exception because you
  502. wrote the following code:
  503.      :Emit(dest, 'subprim, "Send", [t2, t1, Length(node.r3)])
  504.      :PopTemp('ref);
  505. Note the missing semicolon on the first line.  This is parsed as
  506.      (:Emit(blah blah)):PopTemp('ref);
  507. The :Emit call resulted in an 8, which was used as the receiver for the PopTemp message.  This was NOT what the programmer intended.
  508. There are two habits that would have prevented this error. You might want to consider them as part of your personal coding style, though neither of them is extremely important since this error is pretty rare.  
  509.         - Always use "self:foo()" instead of ":foo()".
  510.         - Always put a semicolon at the end of a statement, even  when you don't need to.
  511.     ___________________________________________
  512. Classical OOP programming withNewtonScript (12/17/93)
  513. (Obsoleted by NS Guide 1.0 Final Documentation)
  514.     
  515. Q:  I would like to see the ability to use more of a C++ approach, where I could inherit code —     not necessarily user-interface (view) oriented code — with functionality like templates.     
  516.     
  517. A: You can easily simulate most aspects of traditional class-instance OO programming (as in Smalltalk or C++) using NewtonScript.  There aren't any specific features in NTK 1.0 to support this, but you can do it without too much trouble, using the Project Data window.
  518.     The basic idea is to use _parent inheritance to provide the link between "instances" and "classes".  You define a frame in the Project Data to hold the methods (this is the "class"), and you construct "instances" whose slots are the "instance variables" (or "members" if you prefer C++).  Quotes will continue to be used around these words to emphasize that there is no built-in concept of a class in NewtonScript; we are using the prototype-based inheritance system to simulate class-based inheritance.
  519.     Suppose we want to create a "class" to represent a stack.  We will represent the stack as an array.  Each "instance" needs to store the array and the index of the top element of the stack, so an "instance" will look like this: 
  520.     { _parent: ...,                 // pointer to the "class"
  521.       items: [...],                 // array of items
  522.       topIndex: 2 }                 // index of top item
  523.     The "class" contains the methods, like so:
  524. Stack :=    
  525.         { Push:     func (item) begin
  526.                             topIndex := topIndex + 1;
  527.                             items[topIndex] := item;
  528.                             self
  529.                         end,
  530.         
  531.               Pop:      func () begin
  532.                             if :IsEmpty() then
  533.                                 NIL
  534.                             else begin
  535.                                 local item := items[topIndex];
  536.                                 items[topIndex] := NIL;
  537.                                 topIndex := topIndex - 1;
  538.                                 item
  539.                             end
  540.                         end,
  541.         
  542.               IsEmpty:  func ()
  543.                             topIndex = -1,
  544.               Clone:    func () begin
  545.                             local new := Clone(self);
  546.                             new.items := Clone(new.items);
  547.                             new
  548.                         end,
  549.               New:      func ()
  550.                             {_parent: self,
  551.                              items: Array(10, NIL),
  552.                              topIndex: -1}
  553.             }
  554.     Obviously, this ignores such niceties as stretching the array and signalling error conditions, for the sake of clarity.
  555.     To get a new Stack "instance", you send the New message to the "class":
  556.     s := Stack:New();
  557.     Now you can send messages to s to get work done:
  558.     s:Push('a)
  559.     x := s:Pop()
  560.     if s:IsEmpty() then ...
  561.     s2 := s:Clone()
  562.     // etc.
  563.     You can put "class variables" and "class methods" in the "class" if you want; they're all the same thing in this model, just slots of the "class". The New method is an example.  Note that you can get a new instance from an old instance (i.e., s:New()) because of this unity.
  564.     Those who have been paying attention to the Listener output may already have noticed this method of programming, because it is used by soups, stores, and cursors.  (But you should assume that anything undocumented you notice in the Inspector may be changed in the next ROM.)
  565.     To use this technique in NTK, you can put the "class" in the Project Data window. To access it from your code, you'll need to put a slot that refers to it in your main view (or lower down if you don't need the class throughout your application).  You can just add a slot called "Stack" whose value is "Stack", or if you prefer, you can use distinct names (for example, call it "StackClassFrame" in Project Data).
  566.     Here's an example, in NTK text-export form.  This does not include the project data section, because it looks just like the "Stack :=" section above.  This is just an application with a button that prints "30" in a complicated way using a stack object.
  567. main :=
  568.    {title: "xxx",
  569.     viewBounds: {left: -1, top: 0, right: 236, bottom: 333},
  570.     Stack: Stack,
  571.     _proto: protoapp,
  572.    };
  573. _view000 := /* child of main */
  574.    {text: "Button",
  575.     buttonClickScript:
  576.       func()
  577.       begin
  578.          local s := Stack:New();
  579.          s:Push(10);
  580.          s:Push(20);
  581.          Print(s:Pop() + s:Pop())
  582.       end,
  583.     viewBounds: {left: 74, top: 74, right: 154, bottom: 106},
  584.     _proto: prototextbutton
  585.    };
  586.     You can use an extended form of this technique to put an object-oriented interface on soup entries.  "Wrap" the soup entry in an "instance" frame like the one above by pointing a slot of the "instance" to the soup entry.  You can have "class methods" to do queries and return these "instances". You can also have  "instance methods" to change, validate, undo, flush, and so on.  You can also choose _proto as the slot that points to the soup entry, so you inherit the entry's slots--but remember that slot assignments will go into the "instance", not the entry.
  587.     If you're intrigued by all this, see  the various papers on the language "Self", by Ungar, Chambers, and others at Stanford (now at SunSoft).  Many aspects of NewtonScript were inspired by Self. The postscript files are available via ftp on Internet from self.stanford.edu.
  588.     ___________________________________________
  589. Only 7-Bit ASCII In NewtonScript Symbols (1/26/94) (Obsoleted by NS Guide 1.0 Final Documentation)
  590. Q:    My frame has some slot symbols that contain accent and special letters. For example:
  591.     f := {|à|:"help me please", |é|:"Thanks in advance", ...,...}
  592.     My program received a letter from ProtoInputLine and turned it into a symbol. I have tried many different ways to do this but I could not convert it into a symbol. 
  593. A:    The basic problem is you can only use 7-bit ascii in symbols.
  594.     ___________________________________________
  595. Nested IF Statements, Constant Condition Problems (6/9/94)
  596. Q:     I have found a mysterious problem with Scripts containing  nested IFs. In some cases like the following example they are executed in an abnormal way.
  597.     The true conditions in the real code are constants defined in the project data file with values true or nil. These are used for conditional compiling.
  598.     protoApp.viewSetupDoneScript : FUNC ()
  599.     begin
  600.      if TRUE then
  601.         begin
  602.          if TRUE then
  603.             begin
  604.              if TRUE then
  605.             begin
  606.                  if TRUE then
  607.                     begin
  608.                       Print ("Idlescript1");
  609.                    end
  610.             end
  611.         end
  612.         end;
  613.       Print ("Idlescript2");
  614.     end
  615.     There should be only two prints. In fact there are five prints in the following
  616.     manner:
  617.     "Idlescript1"
  618.     "Idlescript1"
  619.     "Idlescript1"
  620.     "Idlescript1"
  621.     "Idlescript2"
  622.     If I define Boolean slots with value truein the base view, and if I use those slots as conditions, the code works like it should. Why can nested IFs with constant conditions work like a loop? 
  623. A:     This is a bug in the compiler's handling of IF statements with constant conditions.  The bug occurs only if the result of the IF statement is not used.  For example,
  624.     func () begin
  625.         if TRUE then
  626.             if TRUE then
  627.                 Print(1);
  628.         Print(2);
  629.     end
  630.     will trigger the bug, but
  631.     func () begin
  632.         local x := if TRUE then
  633.                        if TRUE then
  634.                            Print(1);
  635.         Print(2);
  636.     end
  637.     will not.
  638.     The workaround is to use the result of the if statement.  You don't really want to keep the result around, so the above example is not recommended .  The simplest  workaround is probably the following:
  639.     func () begin
  640.         (
  641.             if TRUE then
  642.                 if TRUE then
  643.                     Print(1);
  644.         ) and TRUE;
  645.         Print(2);
  646.     end
  647.     This works because the NTK 1.0.1 compiler does not throw away the "and true" part, but the result of the "if" is dropped immediately.
  648.     ___________________________________________
  649. NEW: How to Avoid _parent Problems (6/28/94)
  650. Q:    I read somewhere that developers should never access a view _parent slot directly? Are there any cases when it is safe to access the _parent slot?
  651. A:    In most cases, you should use the :Parent() view method to determine a parent view. However, there are some cases when you want to access the _parent slot of a view directly.  The situation which is bad is to use _parent as a simple variable because results will vary depending on implementation of the current function. Some guidelines:
  652.              _parent    is bad
  653.          view:Parent()  is OK
  654.         self._parent    is OK (and should be the same as :Parent())
  655.         view._parent    is OK (and should be the same as view:Parent())
  656. _____________________________________________
  657. î◊#ˇ ˇˇˇˇ#◊ 
  658. d, Palatino
  659.     .+l+!Newtonscript Programming Language,Times
  660. $°dONLNd)âMü+;8 NEWTONSCRIPT°dONLNd
  661. Mãqù+$ PROGRAMMING°dONLNdq∞ïx+%$LANGUAGE,     Helvetica
  662. °dONLNd"ï~°ò(Ωú<© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved
  663. °dONLNd_™*ºÏ(◊H-_____________________________________________
  664. °dONLNdèÿNıÊ+$6 Introduction
  665. °dONLNdúN˚*,[This document addresses NewtonScript Programming Language  issues that are not available in°dONLNd¯N)Ò* _the currently printed documentation . Please note that this information is subject to change as°dONLNdX)N5f* 9the Newton technology and development environment evolve.
  666. °dONLNdíON_Ï*)TABLE OF CONTENTS:,    Geneva
  667. °dONLNd•_Nl2**• NEW: NewtonScript Object Sizes (6/30/94)°dONLNd–kNxñ* A• Play Catch - NewtonScript Exceptions (Obsoleted by NS Guide 1.0°dONLNdwNÑ√*     Final Documentation)
  668. °dONLNd+ìN£“*NewtonScript Q&As
  669. °dONLNd=£N∞Ê*O• Garbage Collection (10/15/93) (obsoleted by NS Guide 1.0 Final Documentation)°dONLNdçØNº * $• Order of Slots in Frames (9/15/93)°dONLNd≥ªN»Ù* • Structured Literals (9/15/93)°dONLNd‘«N‘Ò* • Passing Arguments (9/15/93)°dONLNdÛ”N‡* "• Slot (Variable) Lookup (9/15/93)°dONLNdflNÏ‚* Q• Testing the Existence of a Slot (Variable) (9/15/93) (Obsoleted by NS 1.0 Final°dONLNdiÎN¯§*    Documentation)°dONLNd{˜N‡* P• Calling Methods Out Of Slot Context (9/15/93) (Obsoleted by NS Guide 1.0 Final°dONLNdÕN§*    Documentation)°dONLNdflNª* F• Inherited (10/13/93) (Obsoleted by NS Guide 1.0 Final Documentation)°dONLNd&N(«* J• Deeply (foreach deeply in...) (10/13/93)(Obsoleted by NS Guide 1.0 Final°dONLNdr'N4§*    Documentation)°dONLNdÑ3N@€* L• Compile Function (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)°dONLNd—?NL¯*  • Function Definitions (10/9/93)°dONLNdÚKNXÒ* P• Closures and Perform (10/9/93) (Obsoleted by NS Guide 1.0 Final Documentation)°dONLNdCWNd€* K• Symbol Hacking (11/11/93) (Obsoleted by NS Guide 1.0 Final Documentation)°dONLNdècNp* !• Literals and Runtime (11/11/93)°dONLNd±oN|Â* M• Missing SemiColons cause Weird Errors (12/11/93) (Obsoleted by NS Guide 1.0°dONLNd{Nà¿*    Final Documentation)°dONLNdáNî˛* R• Classical OOP programming ala NewtonScript (12/17/93) (Obsoleted by NS Guide 1.0°dONLNdlìN†¿*    Final Documentation)
  670. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  671.     °dONLNdˇˇ)¯1ˇ ∞◊#ˇ ˇˇˇˇ#◊ 
  672. d, Palatino
  673.     .+l+!Newtonscript Programming Language,    Geneva
  674. °dONLNd)N6Ï*'O• Only 7-Bit ASCII In NewtonScript Symbols (1/26/94) (Obsoleted by NS Guide 1.0°dONLNdQ5NB¿*    Final Documentation)°dONLNdiANNÑ* <• Nested IF Statements, Constant Condition Problems (6/9/94)°dONLNd¶MNZK* .• NEW: How to Avoid _parent Problems (6/28/94),    Monaco
  675.     °dONLNd’Å*å¯(©HM_____________________________________________________________________________
  676. °dONLNd$öN™\+$(NEW: NewtonScript Object Sizes (6/30/94),     Helvetica°dONLNdM∏N«Ä*Generic
  677. °dONLNdUΔN“ı* ]The Newtonscript Objects are the objects that either reside in the read-write memory,  pseudo°dONLNd≤Δı“˘(Ó-°dONLNd≥“NfiÈ(˙lXROM memory or inside the package or ROM. These objects are aligned to 8-byte boundaries.°dONLNd fiNÍÏ* [This alignment causes a very small amount of fragmentation (usually under 2%) so this issue°dONLNdhÍNˆô* could be ignored.
  678. °dONLNd{Nò*(
  679. Immediates
  680. °dONLNdÜN*È* \The Newton Object System has four built-in primitive classes that describe an object's basic°dONLNd„*N6—* Vtype: Immediates, binaries, arrays and frames. In the case of an Immediates (integers,°dONLNd:6NB|* Echaracter, boolean and so on)  we are dealing with a 30+2 bit object.°dONLNdÇNNZ¸*bIn the case of binaries, arrays and frames we are also dealing with objects containing a so called°dONLNdÂZNfí* Object Header.
  681. °dONLNdÙÄNè©*(
  682. Object Header
  683. °dONLNdéNöÔ* _Every object has a 12-byte header that contains information concerning size, flags, class, lock°dONLNdböN¶^* =count and so on. This information is implementation specific.
  684. °dONLNd†¿Nœz*(Strings
  685. °dONLNd®ŒN⁄ÿ* ZA string object contains a 12 byte header plus the Unicode strings plus a null termination°dONLNd⁄NÊæ* Ocharacter. Note that Unicode characters are two-byte values. Here's an example:,
  686. Courier°dONLNdSÚ¸˛P+Æ"Hello World!"°dONLNdbNÏ(0l_This string contains 12 characters, in other words it has 24  bytes. In addition we have a null°dONLNd¬N ˝* ftermination character (24  + 2 bytes) and an object header  (24 + 2 + 12 bytes), all in all the object°dONLNd) N,ı* `is 38 bytes big. Note that we have not taken into account any possible savings if the string was°dONLNdä,N8!* -compressed (using the NTK compression flags).
  687. °dONLNd∏PN_©*&Binary Objects
  688. °dONLNd«^Njô* LA binary object contains  a 12 byte header plus the size of the actual data.
  689. °dONLNdÑNì£*(
  690. Array Objects
  691. °dONLNd"íNû÷* XArray objects have an object header (12 bytes) and additional four bytes per element. In
  692. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  693.     °dONLNdˇˇ)¯2ˇD◊#ˇ ˇˇˇˇ#◊ 
  694. d, Palatino
  695.     .+l+!Newtonscript Programming Language
  696. °dONLNd)N5Ì*&^addition you need to calculate the amount of data stored in the arrays as well (references) if°dONLNd_5NAˇ* 'you want to calculate the total amount.°dONLNdáMNY•*Here's an example:,
  697. Courier°dONLNdöe·qk+ì["Hello World!", "foo"]°dONLNd≤{NáÈ(£l^We have a header (12 bytes) plus four bytes per element (12  + (2 * 4)  bytes). In addition we°dONLNdáNìÁ* ahave string objects that we refer to  (12 + (2*4) + 38 + 20 bytes), all in all 78 bytes. Again we°dONLNdsìNü˚* ahave not taken into account savings concerning compression. Note that the string objects could be°dONLNd’üN´* ^referred by other arrays and frames as well, so if we want to take this into account we should°dONLNd4´N∑>* 6make sure the string is counted only once per package.,     Helvetica
  698. °dONLNdkœNfi´*&
  699. Frame Objects
  700. °dONLNdy›NÈı* ZWe have two kinds of frames, frames that don't have a shared map object, and frames who do°dONLNd‘ÈNıµ* Ohave a shared map object. We take the simple case first (no shared map object).°dONLNd$N
  701. ˜*_An array object map is an array of symbol pointers and one additional slot. The actual frame is°dONLNdÑ
  702. N»* Vtwo arrays, one contains the slot names, and the other contains the actual slot entry.°dONLNd€%N1Ó*_The map is 16 bytes, if we add the object header to this the basic header size of a frame is 28°dONLNd;1N=Ó* ^bytes.  If we want to add the size taken by slot entries we multiply N slots with 8 (two array°dONLNdö=NIÕ* entries). Here's an example:°dONLNd∑U’aw+á{Slot1: 42, Slot2: "hello"}°dONLNd”kNwÒ(ìlaWe have a header of 28 bytes, in addition we have two slots (28 + (2 * 8)), all in all  48 bytes.°dONLNd5wNÉY* =Once again we didn't calculate the actual slot entry objects.°dONLNdsèNõı*\In the case of a frame with a shared map multiple similar frames (look the same) could share°dONLNd–õNßÚ* [the one and only map. This will save space, reducing the marginal overhead per frame to the°dONLNd,ßN≥Ï* \same as an array with the same amount of slots. In addition we need to take into account the°dONLNdâ≥Nøˆ* \amortized map size that multiple frames share. In other words the magic formula this time is°dONLNdÊøNÀÀ* V12 bytes for the header plus  4 times the amount of slots plus the amortized map size.°dONLNd=◊N„.*/Here's an example of a frame with a shared map:°dONLNdmÔ’˚w+á{Slot1: 42, Slot2: "hello"}°dONLNdâN˚(-l`We have a header of 12 bytes, in addition we have two slots (2 * 4), and additional 16 bytes for°dONLNdÍN¯* athe size of a map with no slots, all in all 36 bytes. We should also take into account the shared°dONLNdLN)Ã* Vmap, in the worst case there's only one of these frame objects, in other words we have°dONLNd£)N5©* additional 16 bytes.°dONLNd∏ANM!*,When do we create objects with a shared map?°dONLNdÂYNe¸*_1. When we clone the system will make sure that the cloned object uses the same map. A trick to°dONLNd    EeNqÙ* \make use of this is to create a common template frame, and when we need to create additional°dONLNd    ¢qN}5* 2frames we clone this template frame over and over.°dONLNd    ’âNïÓ*\2. The system will make sure that the frame uses a shared map if the frame is created by a a
  703. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  704.     °dONLNdˇˇ)¯3ˇ
  705. ◊#ˇ ˇˇˇˇ#◊ 
  706. d, Palatino
  707.     .+l+!Newtonscript Programming Language
  708. °dONLNd)N5ˆ*&aframe constructor expression in most cases a function that returns a frame. This is the reason we°dONLNdb5NAÂ* Yuse RelBounds when we create the viewBounds frame, in other words there's just one single°dONLNdºANMk* =viewBounds map in the system, and it's stored inside the ROM.°dONLNd˙YNe˚*dNote again that these figures are for objects in their runtime state, ready for fast access. Objects°dONLNd_eNq¸* ain transit or in storage (packages) are compressed into smaller stream formats. These figures are°dONLNd¡qN}Î* `neither true for flattened objects that are sent over a comms endpoint, neither true for objects°dONLNd"}Nâí* stored in soups.,     Helvetica
  709. °dONLNd3£N≤Ñ*(Symbols
  710. °dONLNd;±NΩ‡* ZAsymbol is a frame with two slots, one pointing to a string containing the name, the other°dONLNdñΩN…ı* ^pointing to the next symbol in an internal  hash table.  Symbols share one map, so each symbol°dONLNdı…N’Ê* \occupies 12+2*4 = 20 (round to 24) bytes for the frame and 12+length (rounded) bytes for the°dONLNdR’N·Ò* %name, for a total of 36+length bytes.°dONLNdxÌN˘“*WA symbol is a binary object that contains a four-byte hash value and the name is a null°dONLNd–˘O˘+ ^terminated ASCII character . Each symbol is 12 (header) + 4 (hash value_) + length of object +°dONLNd/O˚* &1 bytes (null termination ASCII char).
  711. °dONLNdV$*7ò(QH$PLAY CATCH - NEWTONSCRIPT EXCEPTIONS
  712. °dONLNd{7NGy+$0(9/15/93) (Obsoleted by NS Guide 1.0 final docs)
  713. °dONLNd¨^*qâ(ãH Introduction
  714. °dONLNdπqN}Ù+$\The NewtonScript exception system provides a structured way for a module to report a failure°dONLNd}Oâ + Tto another module.  It communicates the type of the failure, and allows (optionally)°dONLNdkâOïÃ* Stransmission of data that may explain the reason for the failure.  The NewtonScript°dONLNdøïO°ı* _implemention uses the exception system to report errors (for example, errors in an application,°dONLNd°O≠˜* cfailures due to lack of resources, or internal errors).  Developers can use the exception system to°dONLNdÉ≠Oπq* ?communicate errors between different modules in an application.
  715. °dONLNd√ƒ*◊â(ÒH Basic Syntax
  716. °dONLNd–◊N„ˆ+$%The Exception handling is based on a ,
  717. Courier°dONLNdı◊ˆ„,)®    try block°dONLNd˛◊,„ )6$, and if an exception is thrown from°dONLNd#„OÔD( m5somewhere, the code should catch this with a special °dONLNdX„DÔÜ)ı onException°dONLNdc„ÜÔ£)B block.
  718. °dONLNdk *ú(8HTry Statements
  719. °dONLNdzN*+$+The general format of the try statement is:°dONLNd¶5NA`*try°dONLNd´@rL“+$ <statement list>°dONLNdºKNW(sl!onexception <exception symbol> do°dONLNdflVrb¥+$ <statement>°dONLNdÎaNm(âl!onexception <exception symbol> do°dONLNdlrx¥+$ <statement>°dONLNdwNÉ`(ül...°dONLNdéNö—*An example of this might be:
  720. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  721.     °dONLNdˇˇ)¯4ˇ∞◊#ˇ ˇˇˇˇ#◊ 
  722. d, Palatino
  723.     .+l+!Newtonscript Programming Language,
  724. Courier
  725. °dONLNd5NA`*2try°dONLNd@NLl* begin°dONLNd KrWh+$ )// create entries and store them to soups°dONLNd5VNb`(~lend°dONLNd9aNm* !onexception |ext.ex.store.err| do°dONLNd[lNxl* begin°dONLNdbwrÉ»+$ 9// problems with the store, most likely not enough memory°dONLNdùÇréÃ* // do something°dONLNd≠çNô`(µlend°dONLNd±§N∞‹*WThe <exception symbol>s  must be single part exception symbols. Details about exception°dONLNd    ∞Oºâ+ Dsymbols — that is,  what multiple parts mean —  are discussed below.°dONLNdN»N‘˙(l_One or more onexception clauses are allowed. The try statement executes <statement list>. If no°dONLNdÆ‘O‡˛+ bexceptions are thrown in the process, then the value of the try statement is the value of the last°dONLNd‡OϨ* Mstatement in <statement list> and the onexception clauses are never executed.°dONLNd_¯N˚( l`If during execution of <statement list> an exception is thrown, then the execution of <statement°dONLNd¿O¯+ blist> stops and control is transferred to one of the onexception clauses. When an exception, X, is°dONLNd#OÂ* \raised, the onexception clauses of the try statement are examined in order. The first clause°dONLNdÄO(˘* ^whose <exception symbol> is a prefix of any of X's parts is executed and its <statement> value°dONLNdfl(O4* 'becomes the value of the try statement.°dONLNdANM‘(ilXIf no onexception clause matches the exception, then the exception is passed to the next°dONLNd`MOYˆ+ ^enclosing try statement for processing. In a Newton application, the exception will ultimately°dONLNdøYOe˛* `be handled by the view system (putting up an error dialog box) if your application doesn't catch°dONLNd eOqZ* it.°dONLNd$}Nâ˘(•l^NOTE:  It is important that the search for a matching onexception clause uses dynamic scoping,°dONLNdÉâOï•+ not lexical scoping.°dONLNdò°N≠Ê(…l\Since all exceptions have an evt.ex part, an exception clause with evt.ex as its symbol will°dONLNdı≠Oπ‘+ Zcatch any exception. (See the following section for a description of "parts".) If your try°dONLNdPπO≈˚* dstatement has an evt.ex clause,  it should be last, since onexception clauses occuring after it will°dONLNdµ≈O—Ï* ^never be executed. In general, you should order your onexception clauses from most specific to°dONLNd—O›é* least specific.
  726. °dONLNd$È*¸∏(HException Symbols
  727. °dONLNd6¸NÈ+$VExceptions have names which are symbols.  These symbols have a particular format which°dONLNdçOÚ+ ^must be adhered to.  An exception name consists of one or more parts separated by semi-colons.°dONLNdÌO >* 5Each part is a structured name beginning with evt.ex.°dONLNd$,N8Ù(Tl%A  few facts about exception symbols:°dONLNdK8rD6+$ *• They can have as many as 127 characters.°dONLNdwDrPÿ* R• They can contain periods, so the symbols must be enclosed in vertical bars (|'s)°dONLNdÀPr\z* 9• They can have multiple parts, separated by semi-colons.°dONLNd    \rhA* -• They must have a part starting with evt.ex.°dONLNd    4tNÄÏ(úlZThe simplest possible exception symbol is |evt.ex|. An example of an exception symbol with°dONLNd    èÄOå§+ Ktwo parts would be '|evt.ex;type.ref|.  Some more examples: '|evt.ex.div0|,°dONLNd    €åOòÊ* "'|evt.ex.fr.intrp;type.ref.frame|.,     Helvetica
  728. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  729.     °dONLNdˇˇ)¯5ˇ ˛◊#ˇ ˇˇˇˇ#◊ 
  730. d, Palatino
  731.     .+l+!Newtonscript Programming Language
  732. °dONLNd5*H∞(bHException Frames
  733. °dONLNdHNT˝+$]Associated with every exception is an exception frame. When handling an exception you can get°dONLNdoTO`Â+ Ythis frame using the global function, CurrentException(). An exception frame always has a°dONLNd…`OlÛ* \name slot which contains the exception symbol. It will contain one other slot whose name and°dONLNd&lOxÚ* ]contents depend on the type of exception as follows: (this info is summarized on the NS Quick°dONLNdÑxOÑ|*     Ref Card)°dONLNdéêNú˙(∏lc• if  type.ref is a prefix in the exception symbol, then the other slot will be called data and can°dONLNdÚúO®ü+ contain anything.,
  734. Courier°dONLNd∂N¬z(fil2|evt.ex;type.ref|: {name: <string>, data: <frame>}°dONLNd7ÃNÿ˛*HEx: {name: "the llama exception", data : {type: 'inka, size: 42, weight:°dONLNdÄ◊N„l* 177}}°dONLNdÜÓN˙Ó*_• if evt.ex.msg is a prefix in the exception symbol, then the other slot will be called message°dONLNdÊ˙Oß+ and contain a string°dONLNd˚N t(<l1|evt.ex.msg|: {name: <string>, message: <string>}°dONLNd-*N6‡*CEx: {name: "Ho ho exception", message: "You have a serious problem,°dONLNdq5NAr* mate"}°dONLNdxNNZ—*Y• otherwise, the other slot will be called error and will contain an integer (error code)°dONLNd“hNtV*,|evt.ex|: {name: <string>, error: <integer>}°dONLNdˇ~Nä\*-Ex: {:name: "Hi Ho exception", error: -48666}°dONLNd-óN£>*5Here are examples of exception frames from real life:°dONLNdc£NØ⁄* • Example A,  division by zero:°dONLNdÉØNª,* %{name: |evt.ex.div0|, error: 1764744}°dONLNd©ΔN“[*?If you want to catch division by zero errors, here's the trick:°dONLNdÈ“Nfi`* try°dONLNdÓ›rÈÑ+$ 5/0°dONLNdÚËNÙÿ(lonexception |evt.ex| do°dONLNd Ûrˇ‰+$ CurrentException();°dONLNd
  735. NÊ(2l • Example B, undefined variable:°dONLNd@N"¯* G{name: |evt.ex.fr.interp; type.ref.frame|, data: {error:-48807, symbol:°dONLNdà!N-l* foo}}
  736. °dONLNdéD*W(qHHow to Raise Gentle Exceptions
  737. °dONLNd≠cNoÒ+$ZYou can throw an exception using the global function, Throw(<exception symbol>, <exception°dONLNdoO{+ ]data>). The value you pass for <exception data> is put into the "other" slot of the exception°dONLNdf{Oá˜* bframe. Make sure it is the correct type (as per the above rules) or your  call to Throw will raise°dONLNd…áOì£* another exception.,     Helvetica
  738. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  739.     °dONLNdˇˇ)¯6ˇ ‘◊#ˇ ˇˇˇˇ#◊ 
  740. d, Palatino
  741.     .+l+!Newtonscript Programming Language
  742. °dONLNd)N5Ó*&`If the code block has more than one try statement in effect at one time, you can pass control to°dONLNda5OA^+ =the next enclosing try statement using the Rethrow  function.°dONLNd†NNZ(vl[Here are examples of the three different ways to create and throw exceptions. Note that you°dONLNd¸ZOfÒ+ %need to send an exception symbol ('):,
  743. Courier°dONLNd"qN}‰(ôlThrow('|evt.ex.foo|, 99);°dONLNd<áNì*Throw('|evt.ex.msg|, "string");°dONLNd\ùN©Ü*4Throw('|evt.ex;type.ref.something|, ["a", "b", "c"])
  744. °dONLNdëø*“˛(ÏHDefault Exception Handling
  745. °dONLNd¨“Nfifl+$ZUnfortunately, there is currently no general way for your application to specify a default°dONLNdfiOÍÃ+ Sexception handler, for example, viewExceptionScript. This means you need to use try°dONLNd[ÍOˆ3* 1statements wherever you want to catch exceptions.
  746. °dONLNdç*s(.HExamples
  747. °dONLNdñN µ+$SHere's some code  to test out the exception system. This tries various cases and is°dONLNdÍ N,µ* Pdesigned to print no output, assuming  the exception system works as advertised.°dONLNd;,N8ê* FHowever,  the NTK Inspector prints out every exception that is thrown,°dONLNdÇ8NDy* Cwhether it's handled or not. Expect to see output; however, none of°dONLNdΔDNP!* .thePrint("*error?*) statements should execute.°dONLNdı\Xh+
  748. //simple cases & a nested block°dONLNdgXsj* try°dONLNdri~á+ begin°dONLNd$à|îé+try°dONLNd+ìçü}+ (Throw('|evt.ex;type.ref;foo|,"dsafsda");°dONLNdWû癢* Print("*error*1");°dONLNdl©|µÙ(—öonexception |foo| do°dONLNdѥ翴+ begin°dONLNdéøûÀ@+ //Exception handled quietly°dONLNd¨ |÷Ç(Úö °dONLNdÆ ç÷•)end;°dONLNdµ’|·Ç(˝ö °dONLNd∫‡|Ïé* try°dONLNd¡Îç˜}+ (Throw('|evt.ex;type.ref;foo|,"dsafsda");°dONLNd̈ç˘* Print("*error*2");°dONLNd|
  749. ()öonexception |type.ref| do°dONLNd ç´+ begin°dONLNd)û#@+ //Exception handled quietly°dONLNdG"|.Ç(Jö °dONLNdI"ç.•)end;°dONLNdQ8iDG(`á%  //outer block should catch this one°dONLNdyC|O+ Throw('|evt.ex.foobar|,42);°dONLNdòNçZì+  °dONLNdúYie·(Åá  Print("*error*3");°dONLNd≤oi{{*end°dONLNd∂zXÜ‚(¢vonexception |evt.ex| do°dONLNdœÖiëM+ &if CurrentException().error <> 42 then°dONLNd¯ê|úö+ begin,     Helvetica
  750. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  751.     °dONLNdˇˇ)¯7ˇ    V◊#ˇ ˇˇˇˇ#◊ 
  752. d, Palatino
  753.     .+l+!Newtonscript Programming Language,
  754. Courier
  755. °dONLNd)ç5˘+?&Print("*error*4");°dONLNd4ç@#* Print(CurrentException())°dONLNd2?|Kî(göend;°dONLNd7kXw (ìv//try out rethrow()°dONLNdKvXÇj* try°dONLNdPÅiçá+ begin°dONLNd[ó|£é+try°dONLNdb¢çÆ+ Throw('|evt.ex|,42);°dONLNdz≠çπ˘* Print("*error*5");°dONLNdè∏|ƒ(‡öonexception |evt.ex| do°dONLNd™√眴+ begin°dONLNd±Œi⁄Y(ˆá(     //outer block should catch this one°dONLNdfiŸûÂ⁄+5
  756. Rethrow();°dONLNdΉ|Ç( ö °dONLNd̉ç•)end;°dONLNdı˙i’("áPrint("*error*6");°dONLNd
  757. |Ç+  °dONLNdi{(8áend°dONLNdX'‚(Cvonexception |evt.ex| do°dONLNd+&i2M+ &if CurrentException().error <> 42 then°dONLNdT1|=ö+ begin°dONLNd]<çH˘+ Print("*error*7");°dONLNdsGçS#* Print(CurrentException())°dONLNdèR|^î(zöend;°dONLNdîsXÙ(õv//try it out with fn calls°dONLNdØ~Xäj* try°dONLNd¥âiïá+ begin°dONLNdøü|´æ+ call func()°dONLNdŒ™ç∂´+ begin°dONLNdÿµû¡∞+ try°dONLNd·¿∞Ö+ 0call func(esym) Throw(esym,42) with ('|evt.ex|);°dONLNdÀ∞◊* Print("*error*8");°dONLNd.÷û‚4(˛ºonexception |type.ref| do°dONLNdM·∞ÌŒ+ begin°dONLNdVÏç¯}(´(     //outer block should catch this one°dONLNdÖ˜¬˛+5
  758. Rethrow();°dONLNdîû§(*º °dONLNdñ∞»)end;°dONLNdû
  759. çü(5´end°dONLNd§|$¨(@öwith ();°dONLNd≤.|:Ë*Print("*error*9");°dONLNd«9|EÇ*  °dONLNdÀDiP{(láend°dONLNdœOX[‚(wvonexception |evt.ex| do°dONLNdËZifM+ &if CurrentException().error <> 42 then°dONLNde|qö+ begin°dONLNdpç|ˇ+ Print("*error*10");°dONLNd1{çá#* Print(CurrentException())°dONLNdMÜ|íî(Æöend;,     Helvetica
  760. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  761.     °dONLNdˇˇ)¯8ˇT◊#ˇ ˇˇˇˇ#◊ 
  762. d, Palatino
  763.     .+l+!Newtonscript Programming Language,
  764. Courier
  765. °dONLNd4X@+
  766. 1Print("no news, is good news");,    Monaco
  767.     °dONLNd X*c¯(ÄHM_____________________________________________________________________________
  768. °dONLNdoçN™G+$BNewtonScript Q&As,     Helvetica
  769. °dONLNdÇΔNÿ¸*1+___________________________________________
  770. °dONLNdÆÿNˇ*>Garbage Collection (10/15/93) (Obsoleted by NS Guide 1.0 Final°dONLNdÌËN¯µ*Documentation)
  771. °dONLNd¸N˝*_In NewtonScript, the run-time module, not the programmer, is responsible for allocating storage°dONLNd\O˙+ dfor objects and for reclaiming the storage of objects that are no longer used. Garbage collection is°dONLNd¡O(Ï* _carried out by the basic object system, so it’s not technically NewtonScript that does it.  The°dONLNd!(O4Û* astorage taken up by an object will be freed sometime after the last reference to that object goes°dONLNdÉ4O@l* away.°dONLNdâLNXfi(tlXOne of the many benefits of garbage collection is that the programmer has to think about°dONLNd‚XOd‚+ [freeing objects only  in a small number of important places, as opposed to dealing with the°dONLNd>dOpÍ* Zconstant background worry that objects must be freed. Wth automatic garbage collection you°dONLNdôpO|4* 6only need to consider disposing objects in rare cases.°dONLNd–àNîÆ(∞lOne place where you °dONLNd‰àÆîœ)`should °dONLNdÎàœîÚ)!Athink about it is when you close an application; here you want to°dONLNd-îO†„(ºm_free as much storage as possible. You do this by either removing slots  or by setting slots to °dONLNdåı(ºnil°dONLNdê†O¨Ó(»m`in the application's context frame.  Setting the value of all slots and variables referring to a°dONLNdÒ¨O∏¶* particular object to °dONLNd¨¶∏∏)Wnil°dONLNd    ¨∏∏û)4 allows the Garbage Collector to destroy the object.°dONLNd>ƒN–˙(Ïl\Within the Newton operating system, automatic garbage collection is triggered every time the°dONLNdõ–O‹¸+ _system runs out of memory. There's not really any reason to invoke garbage collection manually.°dONLNd˚‹OËú* JHowever, if you must do so, you can call the global NewtonScript function °dONLNdE‹úË®(∫GC°dONLNdG‹®Ë·)
  772. . Consult the°dONLNdUËOÙ–(mNewton Programmer’s Guide°dONLNdnË–ÙG)Å to find out more about the °dONLNdäËGÙY)wGC °dONLNdçËYÙÄ)    function.
  773. °dONLNdòN¸(-l+___________________________________________
  774. °dONLNdƒN"%*"Order of Slots in Frames (9/15/93)
  775. °dONLNdË2N>[*Q: °dONLNdÏ2`>◊)SThe description of the foreach function in the manual might be taken as a hint that°dONLNd@>`Jÿ* Uslots in frames are ordered.  Does slot or array order imply anything about layout of°dONLNdñJ`V* #data in memory (as with C structs?)°dONLNd∫bNn[(älA: °dONLNdæb`n⁄)USlots are not ordered, nor have we seen any performance gains from ordering slots for°dONLNdn`z—* Uparticular sequences or search criteria. Don’t count on their being in any particular°dONLNdjz`ܵ* Lorder, nor on data structures in memory being ordered with any regard to the°dONLNd∑Ü`í¶* Fplacement of slots (as in the ANSI Common LISP object extension CLOS).
  776. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  777.     °dONLNdˇˇ)¯9ˇ
  778. ∂◊#ˇ ˇˇˇˇ#◊ 
  779. d, Palatino
  780.     .+l+!Newtonscript Programming Language
  781. °dONLNd5NAY*2Q:°dONLNd5`Au)<Where is a newly-defined slot placed in a frame? at the end?°dONLNd@MNYY(ulA:°dONLNdCM`Yƒ)PBecause slots are unordered, the location of a new slot cannot be predetermined.,     Helvetica
  782. °dONLNdïuNá¸(¢l+___________________________________________
  783. °dONLNd¡áNó*Structured Literals (9/15/93)
  784. °dONLNd‡ßN≥[*Q: °dONLNd‰ß`≥≈)TIs it really dangerous to assign a string literal to a variable, as in the following°dONLNd9≥`øå* example?,
  785. Courier°dONLNdCÕrŸ¥+ s := "abc";°dONLNdOÊNÚ[(lA: °dONLNdSÊ`Ú_)9That depends on what you're going to do with s. If you're°dONLNdéÚ`˛m* ?going to modify it, then yes, it's dangerous. In that case, you°dONLNdœ˛`
  786. è*
  787. should use°dONLNd‹r$fi+s := Clone("abc");°dONLNd1`=g(Y~;In general you should treat string literals in NewtonScript°dONLNd-=`IÜ* Bas read-only (just as you should in ANSI C). String literals might°dONLNdqI`UÇ* @reside in read-only memory or share storage with other literals.°dONLNd≥a`mÕ*PThe same warning applies to quoted array and frame literals, as in the following°dONLNdm`yä* example:°dONLNdárìb+( '[1,2,3] or '{one: 1, two: 2, three: 3}°dONLNd8†`¨æ(»~NHere are some rules regarding string literals and quoted array/frame literals:°dONLNdà∏`ƒP*5- Treat them as read only. Use clones when necessary.°dONLNd¡–`‹º*M- Realize that they always represent the same object.   In the example below,°dONLNdÍrˆˆ+func foo() begin "abc"°dONLNd(ırä* end;°dONLNd,NP(6l °dONLNd0`X)9- always returns exactly the same string - not different,°dONLNdk`&¥* equivalent strings.°dONLNdÄ2`>Å*B- In your code, an unquoted array or frame literal will generate a°dONLNdƒ>`Jï* Fnew array or frame each time it is evaluated. So it’s acceptable for a°dONLNd J`Vh* Afunction to return [1,2,3] or {one: 1,two: 2,three: 3} as long as°dONLNdOV`bµ* they're not quoted.
  788. °dONLNdd|Né¸(©l+___________________________________________
  789. °dONLNdêéNû*Passing Arguments (9/15/93)
  790. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  791.     °dONLNdˇˇ)Û10ˇ
  792. ¶◊#ˇ ˇˇˇˇ#◊ 
  793. d, Palatino
  794.     .+l+!Newtonscript Programming Language
  795. °dONLNd9NE[*6Q: °dONLNd9`EK)3Is NewtonScript call-by-reference or call-by-value?°dONLNd8QN][(ylA: °dONLNd<Q`]œ)QA seemingly simple question. The short answer is “call-by-value,” the litmus test°dONLNdé]`iè*
  796. being that,
  797. Courier°dONLNdöwrÉÍ+ func foo(x) x := 1;°dONLNd∞ê`ú‘(∏~Sdoes not affect the argument passed to it. However, this is not meant to imply that°dONLNdú`®◊* QNewtonScript functions can never make changes to their arguments. If the argument°dONLNdV®`¥Õ* Qhas structure—for example, if it’s an array, frame, or string—then changes to the°dONLNd®¥`¿£* Iinternal structure are persistent. Consider the following code fragments:°dONLNdÚÕNŸT(ıl °dONLNdÙÕrŸˆ)$func foo(x) x[0] := 1;°dONLNd
  798. ÿr‰Ä* -// changes the 1st element of array arguments°dONLNd>Ór˙*func foo(x) x.slot1 := 1;°dONLNdZ˘rz* ,// changes the slot1 slot of frame arguments°dONLNdà`√(:~MDepending on what you’re used to, this example might be confusing because the°dONLNd÷`*œ* Qconcepts of call-by-reference, call-by-value are mixed, and copying arguments are°dONLNd(*`6⁄* Sintertwined (and often misunderstood.) The following discussion of this terminology°dONLNd|6`Bá* Awith respect to other languages may help clarify the differences.°dONLNdøN`ZŒ*OPascal - Supports both call-by-reference (VAR parameters) or call-by-value (the°dONLNdZ`f´* Idefault). When array or record arguments use call-by-value, copies of the°dONLNdYf`r÷* Narrays/records are made and passed in. To Pascal programmers, NewtonScript may°dONLNd®r`~I* 1seem to pass arrays and frames as VAR parameters.°dONLNd€ä`ñà*CC - Only supports call-by-value. Struct (not struct*) arguments are°dONLNd ñ`¢“* Spassed as values; that is, a copy of the struct is passed. However, array arguments°dONLNdt¢`Æ◊* Tpass in the address of the first element of the array. Thus, C programmers will find°dONLNd…Æ`∫&* +the array arguments to be treated normally.°dONLNdˆΔ`“ò*ELISP - Only supports call-by-value. Copies are not made of structured°dONLNd=“`fiŒ* Targuments (lists, structures, arrays, objects,...) Argument passing in Newton Script°dONLNdífi`ÍÁ*  works just like it does in LISP.,     Helvetica
  799. °dONLNd¥¸Nfi()l(________________________________________
  800. °dONLNd›N* Slot (Variable) Lookup (9/15/93)
  801. °dONLNdˇ.N:[*Q: °dONLNd.`:ì)CWhat differences are there among the various ways to access a slot?°dONLNdGFNRY(nlA:°dONLNdJF`RΔ)NThe means by which you access a slot specifies the search path and inheritance°dONLNdôR`^‚* Xmechanisms used to locate it. Each of the five ways to access a slot is described below.°dONLNdÛj`vÏ*•Specifying the slot name only°dONLNdÇ`éd*;If you specify only the name of the slot, as in the example
  802. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  803.     °dONLNdˇˇ)Û11ˇ Z◊#ˇ ˇˇˇˇ#◊ 
  804. d, Palatino
  805.     .+l+!Newtonscript Programming Language,
  806. Courier
  807. °dONLNd)r5ú+$&theSlot°dONLNd    @`L…(h~Qthe search begins in the current function frame with lexically-visible variables,°dONLNd[L`Xfl* Wfollowed by slot names. In other words, if the currently-executing function has a local°dONLNd≥X`d * Pvariable named theSlot, it is found before a local variable named theSlot in the°dONLNdd`pŒ* Tenclosing function, and so on. Similarly, any of those variables are found (in scope°dONLNdYp`|·* Worder) before an actual slot named theSlot is found. If a variable named theSlot is not°dONLNd±|`à„* Yfound, global variables are searched next. If a global variable is not found, the current°dONLNd à`î,* .receiver is searched for a slot named theSlot.°dONLNd;†`¨¡*QIf the slot is not found in the receiver of the message, the remaining frames are°dONLNdç¨`∏⁄* Tsearched in order of prototype and parent inheritance. An exception is thrown if you°dONLNd‚∏`ƒ * Utry to access a slot that can't be found.  If you do an assignment operation using an°dONLNd8ƒ`–À* Wundeclared slot, the slot is created if you place the self. prefix in front of the slot°dONLNdê–`‹◊* Uname; if you do the operation without the self. prefix you will get a local variable.°dONLNdÁÙ`Ÿ*$•Using the dot (.) operator°dONLNd `¬*QIf you use the dot operator to specify the frame and the slot,  as in the example°dONLNdW$r0Δ+myframe.myslot°dONLNdg;`GΔ(c~Tthe search begins in the specified frame.  If the slot is not found in the specified°dONLNdºG`Sÿ* Sframe, the remaining frames are searched in order of prototype inheritance.  Parent°dONLNdS`_›* Winheritance paths are not searched. If the slot does not exist, the system returns NIL.°dONLNdkw`É›*$•Using the GetSlot function°dONLNdàè`õé* If you call°dONLNdñ©rµÍ+GetSlot(frame, slot)°dONLNd≠¬`Œ‹(Í~Vonly the specified frame is searched for the specified slot. Inheritance paths are not°dONLNdŒ`⁄å*     searched.°dONLNdÊ`ÚÙ*•Using the GetVariable function°dONLNd0˛`
  808. é* If you call°dONLNd>r$+GetVariable(frame, slot)°dONLNdY/`;€(W~Ythe search begins in the specified frame.  If the slot is not found in the current frame,°dONLNd≥;`G…* Othe remaining frames are searched in order of prototype and parent inheritance.°dONLNd_`k'*$)•GetVar will be removed from the language°dONLNd.wNÉ˝(ül_You can usually simulate GetVar using GetVariable(self,slot). The difference will be that local°dONLNdéÉOè˛+ )variables will not be found - only slots.,     Helvetica
  809. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  810.     °dONLNdˇˇ)Û12ˇ ∂◊#ˇ ˇˇˇˇ#◊ 
  811. d, Palatino
  812.     .+l+!Newtonscript Programming Language
  813. °dONLNd)N5˘*&`If you use GetVar you may find that is not available in future products, in which case your code°dONLNda5OA˘+ ]will throw an exception; or  GetVar may work differently not finding local variables anymore,°dONLNdøAOM´* Kin which case your code may subtly break. DTS advises against using GetVar.,     Helvetica
  814. °dONLNd [Nm¸(àl+___________________________________________
  815. °dONLNd8mN}¯*ETesting the Existence of a Slot (Variable) (9/15/93) (Obsoleted by NS°dONLNd~}NçÚ*1.0 Final Documentation).
  816. °dONLNdòõNß[*Q: °dONLNdúõ`ßÀ)MWhat differences are there among the various ways to determine whether a slot°dONLNdÍß`≥Ø* exists in a frame?°dONLNd˝øNÀY(ÁlA:°dONLNdø`À·)VThe means by which you test for a slot's existence specifies the search path and kinds°dONLNdWÀ`◊Ã* Qof inheritance used to discover it. The following examples describe three ways to°dONLNd©◊`„* ,discover the existence of a slot in a frame.°dONLNd◊Ô`˚Ÿ*• Using the exists operator°dONLNdÙ`÷*TThe exists operator follows the same rules as the expression to which it is applied.°dONLNdI`·* YFor example, if you use this operator to test a slot access expression, as in the example,
  817. Courier°dONLNd§-r9+myframe.myslot exists°dONLNdºF`R€(n~Ythe search begins in the specified frame.  If the slot is not found in the current frame,°dONLNdR`^Ã* Pthe remaining frames are searched in order of prototype inheritance only. Parent°dONLNdg^`j* #inheritance paths are not searched.°dONLNdåv`Ç€*THowever, when using the exists operator to check whether an identifier exists, as in°dONLNd·Ç`éô* the example°dONLNdÓúr®∫+ myvar exists°dONLNd˝µ`¡j(›~9both prototype and parent inheritance paths are searched.°dONLNd8Õ`Ÿ‚*• Using the HasSlot function°dONLNdVÂ`Òé* If you call°dONLNdcˇr Í+HasSlot(frame, slot)°dONLNdy`$‹(@~Vonly the specified frame is searched for the specified slot. Inheritance paths are not°dONLNd–$`0å*     searched.°dONLNd€<`H˘* • Using the HasVariable function°dONLNd˝T``é* If you call°dONLNd
  818. nrz+HasVariable(frame, slot)°dONLNd$á`ì‡(Ø~Zthe search begins in the current frame. If the slot is not found in the current frame, the°dONLNdì`ü∑* Kremaining frames are searched in order of prototype and parent inheritance.
  819. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  820.     °dONLNdˇˇ)Û13ˇ⁄◊#ˇ ˇˇˇˇ#◊ 
  821. d, Palatino
  822.     .+l+!Newtonscript Programming Language,     Helvetica
  823. °dONLNdˇˇ*7+___________________________________________
  824. °dONLNdGNWÈ*>Calling Methods Out Of Slot Context (9/15/93) (Obsoleted by NS°dONLNd?WNg*Guide 1.0 Final Documentation)
  825. °dONLNd^wNÉ[*Q: °dONLNdbw`ÉΔ)SI'm trying to pull a method out of a slot and call it. Unfortunately, the functions°dONLNd∂É`è}* Aapply and call both seem to set self to {}. Is there another way?°dONLNd¯õNß[(√lA: °dONLNd¸õ`߀)OThe global function Perform(frame, message, paramaterArray) does what you want,°dONLNdLß`≥›* Wexcept that the method needs to be in a slot in the current frame if you really want to°dONLNd§≥`ø÷* preserve the value of self.
  826. °dONLNd¡ N‹¸(˜l+___________________________________________
  827. °dONLNdÌ‹NÏû*5Inherited (10/13/93) (Obsoleted by NS Guide 1.0 Final°dONLNd#ÏN¸µ*Documentation)
  828. °dONLNd2 N[*Q: °dONLNd6 `W)6What is the function of "inherited:" and "inherited:?"°dONLNdm$N0‘(LlUA:  In NewtonScript, the inherited:X() message send specifies a NewtonScript function°dONLNd√0`<”+ Scall on the function X, where X is found UP the inheritance chain starting from the°dONLNd<`H÷* Scaller's _proto. In other words, lookup for that method ONLY starts up the caller's°dONLNdkH`T‚* U_proto chain, NOT in  "self" (the currently executing frame). The conditional message°dONLNd¡T``z* send (,
  829. Courier°dONLNd«Tz`Ü):?°dONLNd…TÜ`®) ), with °dONLNd—T®`‰)"
  830. inherited °dONLNd€T‰`‚)<8specified, operates almost exactly the same  except that°dONLNd``lfi(à~Uno error results if the given method (function) is NOT found. The conditional message°dONLNdjl`xz* send (°dONLNdplzxÜ):?°dONLNdrlÜx®) ), with °dONLNdzl®x‰)"
  831. inherited °dONLNdÑl‰x‡)<8specified, is helpful in complex heirarchies because you°dONLNdΩx`Ñÿ(†~Ocan use it without  worrying about whether any such method was ever implemented°dONLNd
  832. Ñ`ê* #higher up in the inheritance chain.
  833. °dONLNd2®N∫¸(’l+___________________________________________
  834. °dONLNd^∫N Ì*BDeeply (foreach deeply in...) (10/13/93)(Obsoleted by NS Guide 1.0°dONLNd° N⁄Ÿ*Final Documentation)
  835. °dONLNd∏N¸[*#Q: °dONLNdº`¸í)AWhat is the difference between "foreach" and "foreach deeply in"?°dONLNd˛N›(0lZA:  'Deeply' specifies that only the slots/elements of the current frame/array are listed,°dONLNdY` “+ Texcept that if passed a frame, slots of ancestors up the _proto chain are considered°dONLNdÆ `,Ê* elements of the current frame.°dONLNdœ8`D§*IHere is some Inspector code to illustrate the difference between the two:°dONLNdPr\“+//oo DEFINITIONS°dONLNd,[rg* normallist := func (param)°dONLNdHfNr`(él   °dONLNdLfrrê)$begin°dONLNdRqN}r(ôl      °dONLNdYqñ})Hlocal tempItem;°dONLNdi|Nàr(§l      °dONLNdp|ñà,)Hforeach tempItem in param°dONLNdãáNì (Øl#                  collect tempItem;°dONLNdØíNû`*    °dONLNd≥írûä)$end;
  836. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  837.     °dONLNdˇˇ)Û14ˇ    æ◊#ˇ ˇˇˇˇ#◊ 
  838. d, Palatino
  839.     .+l+!Newtonscript Programming Language,
  840. Courier
  841. °dONLNd)r5+$&deeplylist := func (param)°dONLNd4N@`(\l   °dONLNd 4r@ê)$begin°dONLNd&?NKr(gl      °dONLNd-?ñK)Hlocal tempItem;°dONLNd=JNVr(rl      °dONLNdDJñVV)H foreach tempItem deeply in param°dONLNdfUNa (}l#                  collect tempItem;°dONLNdä`Nl`*    °dONLNdé`rlä)$end;°dONLNdîårò“*,//oo SAMPLE DATA°dONLNd¶ór£2*  x := {one: 1, two: 2, three: 3};°dONLNd»≠rπ8*!y:= {four: 4, five: 5, combo: x};°dONLNdÎ√rœ*z:= {six: 6, _proto: y};°dONLNdŸrÂ∂*6complex := {a: "first string", b: ["array1", "array2",°dONLNd?‰ñ>+$ {_proto: x}], c: 3.1415926};°dONLNdgr'Æ(Cê
  842. //oo TESTS°dONLNds&r2,* :normallist(x)          // same°dONLNdî1r=‰* #4413441  [1, 2, 3]°dONLNd©<rHΔ* :deeplylist(x)°dONLNdπGrS‰* #44137D9  [1, 2, 3]°dONLNdŒhrt,*!:normallist(y)          // same°dONLNdÔsr¿*
  843. #4413A11  [4,°dONLNd˛~Näú(¶l
  844.            5,°dONLNd
  845. âNï¿*            {One: 1,°dONLNd"îN†¿*             two: 2,°dONLNd7üN´“*             three: 3}]°dONLNdO™r∂Δ+$ :deeplylist(y)°dONLNd_µr¡¿*
  846. #4413C49  [4,°dONLNdn¿NÃú(Ël
  847.            5,°dONLNd}ÀN◊¿*            {One: 1,°dONLNdí÷N‚¿*             two: 2,°dONLNdß·NÌ“*             three: 3}]°dONLNdæN™*!:                        // For z, the answer is different.°dONLNd˙
  848. N‡* C                        // the deeply version travels proto chains!°dONLNd?r$Δ+$ :normallist(z)°dONLNdO#r/¿*
  849. #4416E29  [6,°dONLNd^.N:Δ(Vl           {four: 4,°dONLNdt9NEΔ*             five: 5,°dONLNdäDNP*             combo: {#4415D79}}]°dONLNd≠erqΔ+$!:deeplylist(z)°dONLNdΩpr|¿*
  850. #4416FE1  [6,°dONLNdÃ{Náú(£l
  851.            4,°dONLNd€ÜNíú*
  852.            5,°dONLNdÍëNù¿*            {One: 1,,     Helvetica
  853. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  854.     °dONLNdˇˇ)Û15ˇ ê◊#ˇ ˇˇˇˇ#◊ 
  855. d, Palatino
  856.     .+l+!Newtonscript Programming Language,
  857. Courier
  858. °dONLNd)N5¿*&            two: 2,°dONLNd4N@“*             three: 3}]°dONLNd,UNaÊ*!D                 // for this complex frame, the answers are the same°dONLNdr`Nl¯* G                 // because there is no _proto slot in the *MAIN* frame°dONLNdªkNwº* =                 // hence there is nowhere to go deeply into.°dONLNd˙vrÇÍ+$ :normallist(complex)°dONLNdÅrç* #4418741  ["first string",°dONLNd,åNòV(¥l,           ["array1", "array2", {#44183B9}],°dONLNdZóN£¿*            3.14159]°dONLNdo≠rπÍ+$:deeplylist(complex)°dONLNdÖ∏rƒ* #4418AC1  ["first string",°dONLNd°√NœV(Îl,           ["array1", "array2", {#44183B9}],°dONLNdœŒN⁄¿*            3.14159],     Helvetica
  859. °dONLNd‰ÚN¸*)+___________________________________________
  860. °dONLNdNŒ*;Compile Function (10/9/93) (Obsoleted by NS Guide 1.0 Final°dONLNdLN$µ*Documentation)
  861. °dONLNd[7NC[* Q: °dONLNd_7`C€)TI need the ability to download the validtest and endtest functions to the Newton for°dONLNd¥C`Oœ* Tsearches.  I do not see how I can convert the incoming textual representation of the°dONLNd    O`[7* 2function to code to execute.  How could I do this?°dONLNd<gNsY(èlA:°dONLNd?g`s„)TYou could use the special compile function in NewtonScript. Here's an example of how°dONLNdîs`¢* to use compile:°dONLNd•ãÑó¢+$begin°dONLNd´ñr¢x(æê °dONLNdÆññ¢Ã)$     local x;°dONLNd∏¨r∏x(‘ê °dONLNdª¨ñ∏Ï)$9 // Set x to be a function that returns the new function.°dONLNdı∑r√x(flê °dONLNd¯∑ñ√b)$" x := Compile("Print(\"Hello\")");°dONLNdÕrŸ~(ıê  °dONLNdÕÑŸê)  °dONLNd!ÕñŸå))// Now call the actual compiled function.°dONLNdKÿr‰~(ê  °dONLNdOÿñ‰)$call x with ();°dONLNd_Ór˙~(ê  °dONLNdcÓñ˙‡)$7// At this point, "Hello" will have been printed to the°dONLNdõ˘r∫(!ê inspector...°dONLNd©Ñú+ end;°dONLNdØ`'Œ(C~QNote that compile returns a function taking no arguments whose body is the string°dONLNd'`3€* Wpassed to compile.  If you need to create a function taking arguments, you can create a°dONLNdY3`?–* Qfunction with Compile whose return value is a function that takes arguments, like°dONLNd´?`Kv* this:°dONLNd±Wrch+)f := call Compile("func(x) x*x") with ();°dONLNd€brn8* !call f with (10);  // prints 100.
  862. °dONLNd˛xNä¸(•l+___________________________________________
  863. °dONLNd*äNö *Function Definitions (10/9/93)
  864. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  865.     °dONLNdˇˇ)Û16ˇ ‘◊#ˇ ˇˇˇˇ#◊ 
  866. d, Palatino
  867.     .+l+!Newtonscript Programming Language
  868. °dONLNd9NEY*6Q:°dONLNd9`E€)]Is it "safer" to use a return statement at the end of a function or is it just a style issue?°dONLNdaQN]Y(ylA:°dONLNddQ`]◊)TAll functions return the last value in the function body. This means that you have a°dONLNdπ]`i»* Qchoice of explicitly writing a return statement, or assuming that the code reader°dONLNd i`ua* 8knows that the last statement is automatically returned.°dONLNdEÅ`çÿ*POne might argue that a return statement should always be used. However there are°dONLNdñç`ô„* Vcases where the code looks prettier with no return statement, and the return statement°dONLNdÌô`•d* 7does generate code. Compare the following two examples:,
  869. Courier°dONLNd&±ÑΩ¢+$begin°dONLNd.ºñ»®+ ...°dONLNd4«ñ”,* if expr then "" else text°dONLNdO“Ñfiñ(˙¢end°dONLNdTÛÑˇ¢*!begin°dONLNd\˛ñ
  870. fi+ if expr then°dONLNdl    ®fi+     return ""°dONLNdxñ Æ(<¥else°dONLNdÄ®+Í+ return text°dONLNdç*Ñ6ñ(R¢end°dONLNdíA`Mÿ(i~TAdditionally, in the current NewtonScript compiler, an extra byte or two is used for°dONLNdÁM`Y◊* Uthe return statement, but in most cases it will make no apparent difference in speed.,     Helvetica
  871. °dONLNd>Yrk¯+'_______________________________________°dONLNdekO}w(òm____
  872. °dONLNdj}NçÁ(®l?Closures and Perform (10/9/93) (Obsoleted by NS Guide 1.0 Final°dONLNd™çNùµ*Documentation)
  873. °dONLNdπ©Nµ[*Q: °dONLNdΩ©`µ“)QThe NewtonScript manual indicates that the receiver during a call is the receiver°dONLNdµ`¡* )that made the call. For example, the code°dONLNd=ÕrŸÖ+a := °dONLNdBÕÖŸã){°dONLNdDŸNÂf(l    °dONLNdIŸr¢)$id: "a",°dONLNdR‰Nf( l    °dONLNdW‰rˆ)$foo: func() Print(id),°dONLNdoÔr˚~* };°dONLNdurñ*b := {°dONLNd|Nf(8l    °dONLNdÅr¢)$id: "b",°dONLNdäN'f(Cl    °dONLNdèr',)$bar: func() call a.foo with (),°dONLNd∞&r2~* };°dONLNd∂<rH¢*b:bar();°dONLNd¬S`_¨({~should print "b".°dONLNd◊k`wÃ*QWhen I run this in an Inspector, however, it appears that the receiver during the°dONLNd)w`ÉŒ* Texecution of foo() is the top level frame in which a (and b) is defined.  How is the°dONLNd~É`è≠* Kreceiver actually determined?  Is it always the top level of the Inspector?
  874. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  875.     °dONLNdˇˇ)Û17ˇ
  876. †◊#ˇ ˇˇˇˇ#◊ 
  877. d, Palatino
  878.     .+l+!Newtonscript Programming Language
  879. °dONLNd5NA[*2A: °dONLNd5`AŸ)SWhat you really create is a closure, which is the executable code bound up with the°dONLNdXA`M * Pdynamic and lexical environments at the time the function was created.  That is,°dONLNd©M`Yfl* Rwhatever self evaluated to when the function was compiled is what it will evaluate°dONLNd¸Y`e∑* to when it's called.°dONLNdq`}fi*SThe Perform  call, or message-passing does change the closure's dynamic environment°dONLNdf}`âÆ* K(self) to the frame that was specified by the message pass or Perform call.°dONLNd≥ï`°`*9To do what you seem to be attempting, you could try this:,
  880. Courier°dONLNdÓ≠rπñ+a := {°dONLNdı∏Nƒf(‡l    °dONLNd˙∏rƒ¢)$id: "a",°dONLNd√Nœ`(Îl   °dONLNd√rœ¸)$foo: func() Print(id)};°dONLNd ŸrÂñ*b := {°dONLNd'‰Nf( l    °dONLNd,‰r¢)$id: "b",°dONLNd5ÔN˚f(l    °dONLNd:Ôr˚§)$3bar: func() begin self.temp := a.foo; :temp() end};°dONLNdpr¢*b:bar();°dONLNdz`(À(D~SInstead of :temp() above, you could have used Perform(self, 'temp, []);  Perform is°dONLNdŒ(`4Ã* Mhandy when you don't know at compile time which message you need to pass. For°dONLNd4`@◊* Sexample, you can write Perform(self, jumpTable[i], []); where jumpTable contains an°dONLNdp@`L…* Narray of symbols representing methods. Perform takes a frame, a message and an°dONLNdøL`XÂ* array of message parameters.,     Helvetica
  881. °dONLNd›dNv¸(ël+___________________________________________
  882. °dONLNd    vNÜÀ*:Symbol Hacking (11/11/93) (Obsoleted by NS Guide 1.0 Final°dONLNdDÜNñµ*Documentation)
  883. °dONLNdS¶N≤Y*Q:°dONLNdV¶`≤⁄)RI would like to be able to build frames dynamically and have my application create°dONLNd©≤`æ⁄* Tthe name of the slot in the frame dynamically as well.  For instance, something like°dONLNd˛æ` v* this:°dONLNd r÷J+ $MyFrame:= {}; tSlotName := "Slot_1";°dONLNd-·`Ì=(    ~3At this point is there a way to then create this ?:°dONLNdbÌr˘Δ+ MyFrame.Slot_1°dONLNdqNY(8lA:°dONLNdt`„)XThere is a function called Intern, that takes a string and makes a symbol. There is also°dONLNdÕ`(”* Na mechanism called path expressions (see the NewtonScript manual), that allows°dONLNd(`4fl* Xyou to specify an expression or variable to evaluate, in order to get the slot name. You°dONLNdu4`@8* 2can use these things to access the slots you want:°dONLNd©LrX¸+MyFrame := {x: 4} ;    °dONLNd¬L&Xû)¥// MyFrame -->{x: 4}°dONLNdÿcro¸(ãêtheXSlotString := "x" ;°dONLNdÒnrzP* %MyFrame.(Intern(theXSlotString)) := 6°dONLNdyñÖú+$  °dONLNdy&Ö§)ê// MyFrame --> {x: 6}°dONLNd6êrú(∏êtSlotName := "Slot_1" ; °dONLNdOê&ú⁄)¥// the following code creats a
  884. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  885.     °dONLNdˇˇ)Û18ˇ
  886. .◊#ˇ ˇˇˇˇ#◊ 
  887. d, Palatino
  888.     .+l+!Newtonscript Programming Language,
  889. Courier
  890. °dONLNd)&5˛+ÿ&$// slot called Slot_1 in MyFrame and°dONLNd,4&@Œ* // assigns it the number 7. °dONLNdI?rK>(gê"MyFrame.(Intern(tSlotName)) := 7 ;°dONLNdxJ&VÊ+¥  // MyFrame --? {x: 6, Slot_1: 7}°dONLNdöaNmY(âlQ:°dONLNdùarmÈ)$TIs there a way to look for a slot programmatically starting with a slot name string?°dONLNdÚyNÖY(°lA:°dONLNdıyrÖ)$"Here's the code which can do this:°dONLNdÖrët* +if MyFrame.(Intern(slotToFind)) exists then°dONLNdGêrúŒ* :      x := MyFrame.(Intern(slotToFind)) ;  // use the slot,     Helvetica
  891. °dONLNdÖ≠Nø¸(⁄l+___________________________________________
  892. °dONLNd±øNœ* Literals and run time (11/11/93)
  893. °dONLNd“€NÁY*Q:°dONLNd’€`ÁÀ)UIs the literals slot really needed during run time? I noticed that I could figure out°dONLNd+Á`Û‚* Vquite a lot about how my functions work from the literals used (examining the literals°dONLNdÇÛ`ˇ◊* Wslot). I would rather not make it easy for others to reverse engineer certain routines.°dONLNd⁄ NY(3lA:°dONLNd› `’)TThe literals slot is indeed needed during run time (in the current implementation of°dONLNd2`#®* INewtonScript) The interpreter is using it at run time. Here's an example:°dONLNd}/r;v+f°dONLNd~/v;‹) := func() "abc";°dONLNdë;rGV(cêᄹCB9  <CodeBlock, 0 args #4409CB9>°dONLNdπFrRÆ*
  894. f.literals°dONLNd≈Qr]* #4409B61  [literals: "abc"]°dONLNd‚\rh* f.literals[0] := {foo: 'bar}°dONLNdgrsÍ* #440A1D1  {foo: bar}°dONLNdrr~Δ* call f with ()°dONLNd&}râÍ* #440A1D1  {foo: bar}°dONLNd<î`†‚(º~TDon't assume anything about the implementation of the literals slot in future Newton°dONLNdë†`¨¨* system software.
  895. °dONLNd£ºNŒ¸(Èl+___________________________________________
  896. °dONLNdœŒNfi˙*AMissing Semicolons cause Weird Errors (12/11/93) (Obsoleted by NS°dONLNdfiNÓ*Guide 1.0 Final Documentation)
  897. °dONLNd0˙NÁ*\As with Pascal, semicolons are statement separators, not terminators. If you forget to add a°dONLNdçO‰+ [semicolon at the end of the Newtonscript statement, the interpreter will try to interpret a°dONLNdÈOb* >larger statement than intended, causing strange error reports.°dONLNd(*N6(Rl+The following is an example of such a case.°dONLNdTBNN«*UYou are getting an "expected array, frame, or binary but got 8" exception because you°dONLNd™NNZ¡* wrote the following code:°dONLNdƒfNrR*  °dONLNdΔfRr¥);   :Emit(dest, 'subprim, "Send", [t2, t1, Length(node.r3)])°dONLNdqN}Δ(ôl     :PopTemp('ref);°dONLNdàNîd*@Note the missing semicolon on the first line.  This is parsed as
  898. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  899.     °dONLNdˇˇ)Û19ˇ◊#ˇ ˇˇˇˇ#◊ 
  900. d, Palatino
  901.     .+l+!Newtonscript Programming Language,
  902. Courier
  903. °dONLNd5NA2*2&     (:Emit(blah blah)):PopTemp('ref);°dONLNd'LNX˜*^The :Emit call resulted in an 8, which was used as the receiver for the PopTemp message.  This°dONLNdÜXOd
  904. + %was NOT what the programmer intended.°dONLNd¨pN|˛(òl]There are two habits that would have prevented this error. You might want to consider them as°dONLNd
  905. |OàÎ+ \part of your personal coding style, though neither of them is extremely important since this°dONLNdgàOî¶* error is pretty rare.°dONLNdîN†%(ºl6        - Always use "self:foo()" instead of ":foo()".°dONLNd∂†N¨»* Y        - Always put a semicolon at the end of a statement, even  when you don't need to.,     Helvetica
  906. °dONLNdºNŒ¸*!+___________________________________________
  907. °dONLNd=ŒNfi¡*5Classical OOP programming withNewtonScript (12/17/93)°dONLNdsfiNÓâ*/(Obsoleted by NS Guide 1.0 Final Documentation)
  908. °dONLNd•˙N“*XQ:  I would like to see the ability to use more of a C++ approach, where I could inherit°dONLNd˛`Ç+ code — °dONLNdñ‹)6Hnot necessarily user-interface (view) oriented code — with functionality°dONLNdO`®(:~like templates. °dONLNdc*N6‚(RlXA: You can easily simulate most aspects of traditional class-instance OO programming (as°dONLNdº6`B‹+ Sin Smalltalk or C++) using NewtonScript.  There aren't any specific features in NTK°dONLNdB`NŸ* W1.0 to support this, but you can do it without too much trouble, using the Project Data°dONLNdhN`Zá* window.°dONLNdqf`rÿ*TThe basic idea is to use _parent inheritance to provide the link between "instances"°dONLNdΔr`~‚* Wand "classes".  You define a frame in the Project Data to hold the methods (this is the°dONLNd~`ä—* T"class"), and you construct "instances" whose slots are the "instance variables" (or°dONLNdsä`ñÿ* T"members" if you prefer C++).  Quotes will continue to be used around these words to°dONLNd»ñ`¢÷* Temphasize that there is no built-in concept of a class in NewtonScript; we are using°dONLNd¢`Æ∫* Kthe prototype-based inheritance system to simulate class-based inheritance.°dONLNdj∫`Δfi*VSuppose we want to create a "class" to represent a stack.  We will represent the stack°dONLNd¡Δ`“‚* Was an array.  Each "instance" needs to store the array and the index of the top element°dONLNd“`fi:* 3of the stack, so an "instance" will look like this:°dONLNdNÍNˆº(l=    { _parent: ...,                 // pointer to the "class"°dONLNdåıNå* 5      items: [...],                 // array of items°dONLNd¬N û* 8      topIndex: 2 }                 // index of top item°dONLNd¸`#+*The "class" contains the methods, like so:°dONLNd'/r;¢+Stack :=°dONLNd6:ñFD+$ { Push:     func (item) begin°dONLNdTErQ∞(mê5                            topIndex := topIndex + 1;°dONLNdäPr\™* 4                            items[topIndex] := item;°dONLNdø[rg2*                              self°dONLNd‡frr*                         end,°dONLNd    |ràP*%              Pop:      func () begin°dONLNd    ,árìÜ* .                            if :IsEmpty() then°dONLNd    [írûD* #                                NIL
  909. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  910.     °dONLNdˇˇ)Û20ˇ
  911. ⁄◊#ˇ ˇˇˇˇ#◊ 
  912. d, Palatino
  913.     .+l+!Newtonscript Programming Language,
  914. Courier
  915. °dONLNd)r5V+$&&                            else begin°dONLNd'4r@Ê* >                                local item := items[topIndex];°dONLNdf?rKº* 7                                items[topIndex] := NIL;°dONLNdûJrV»* 9                                topIndex := topIndex - 1;°dONLNdÿUraJ* $                                item°dONLNd˝`rl,*                             end°dONLNdkrw*                         end,°dONLNdCÅrç,*              IsEmpty:  func ()°dONLNdcåròn* *                            topIndex = -1,°dONLNdé¢rÆP*%              Clone:    func () begin°dONLNd¥≠rπ∞* 5                            local new := Clone(self);°dONLNdÍ∏rƒŒ* :                            new.items := Clone(new.items);°dONLNd%√rœ,*                             new°dONLNdEŒr⁄*                         end,°dONLNdb‰r,*              New:      func ()°dONLNdÇÔr˚t* +                            {_parent: self,°dONLNdÆ˙r§* 3                             items: Array(10, NIL),°dONLNd‚rn* *                             topIndex: -1}°dONLNd
  916. r¿*
  917.             }°dONLNd&`2…(N~RObviously, this ignores such niceties as stretching the array and signalling error°dONLNdo2`>˘* $conditions, for the sake of clarity.°dONLNdïJ`V¢*GTo get a new Stack "instance", you send the New message to the "class":°dONLNd›brn+    s := Stack:New();°dONLNdÙy`Ö9(°~0Now you can send messages to s to get work done:°dONLNd%ërùΔ+    s:Push('a)°dONLNd4úr®“*     x := s:Pop()°dONLNdEßr≥*     if s:IsEmpty() then ...°dONLNda≤ræ‰*     s2 := s:Clone()°dONLNduΩr…¥*     // etc.°dONLNdLJ`Ï‹(~UYou can put "class variables" and "class methods" in the "class" if you want; they're°dONLNdÿÏ`¯«* Qall the same thing in this model, just slots of the "class". The New method is an°dONLNd*¯`—* Sexample.  Note that you can get a new instance from an old instance (i.e., s:New())°dONLNd~`ø* because of this unity.°dONLNdñ`(…*LThose who have been paying attention to the Listener output may already have°dONLNd„(`4‘* Unoticed this method of programming, because it is used by soups, stores, and cursors.°dONLNd:4`@⁄* Q(But you should assume that anything undocumented you notice in the Inspector may°dONLNdå@`LÂ* be changed in the next ROM.)°dONLNd™X`d⁄*TTo use this technique in NTK, you can put the "class" in the Project Data window. To°dONLNdˇd`p‡* [access it from your code, you'll need to put a slot that refers to it in your main view (or°dONLNd[p`|fl* Vlower down if you don't need the class throughout your application).  You can just add°dONLNd≤|`àÃ* Ta slot called "Stack" whose value is "Stack", or if you prefer, you can use distinct°dONLNdà`îÅ* ?names (for example, call it "StackClassFrame" in Project Data).,     Helvetica
  918. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  919.     °dONLNdˇˇ)Û21ˇ
  920. “◊#ˇ ˇˇˇˇ#◊ 
  921. d, Palatino
  922.     .+l+!Newtonscript Programming Language
  923. °dONLNd5`A÷+2SHere's an example, in NTK text-export form.  This does not include the project data°dONLNdTA`Mµ* Rsection, because it looks just like the "Stack :=" section above.  This is just an°dONLNdßM`Y€* Uapplication with a button that prints "30" in a complicated way using a stack object.,
  924. Courier°dONLNd˝Yreú+ main :=°dONLNddrpÿ*    {title: "xxx",°dONLNdor{⁄* <    viewBounds: {left: -1, top: 0, right: 236, bottom: 333},°dONLNdTzrÜÿ*     Stack: Stack,°dONLNdfÖrë*     _proto: protoapp,°dONLNd|êrúê*    };°dONLNdǶr≤,*_view000 := /* child of main */°dONLNd¢±rΩ‰*    {text: "Button",°dONLNd∂ºr»ˆ*     buttonClickScript:°dONLNdÕ«r”∫*       func()°dONLNd⁄“rfi¥*       begin°dONLNdÊ›rÈ2*           local s := Stack:New();°dONLNdËrÙÍ*          s:Push(10);°dONLNdÛrˇÍ*          s:Push(20);°dONLNd1˛r
  925. 8* !         Print(s:Pop() + s:Pop())°dONLNdS    rÆ*
  926.       end,°dONLNd^r ‡* =    viewBounds: {left: 74, top: 74, right: 154, bottom: 106},°dONLNdúr+*     _proto: prototextbutton°dONLNd∏*r6ê*    };°dONLNdøL`X‘(t~UYou can use an extended form of this technique to put an object-oriented interface on°dONLNdX`dÀ* Qsoup entries.  "Wrap" the soup entry in an "instance" frame like the one above by°dONLNdgd`p‚* Xpointing a slot of the "instance" to the soup entry.  You can have "class methods" to do°dONLNd¿p`|‚* Vqueries and return these "instances". You can also have  "instance methods" to change,°dONLNd|`à‹* Xvalidate, undo, flush, and so on.  You can also choose _proto as the slot that points to°dONLNdpà`î”* Tthe soup entry, so you inherit the entry's slots--but remember that slot assignments°dONLNd≈î`†* +will go into the "instance", not the entry.°dONLNdÚ¨`∏»*SIf you're intrigued by all this, see  the various papers on the language "Self", by°dONLNdF∏`ƒ∂* JUngar, Chambers, and others at Stanford (now at SunSoft).  Many aspects of°dONLNdëƒ`–Œ* QNewtonScript were inspired by Self. The postscript files are available via ftp on°dONLNd„–`‹Ì*  Internet from self.stanford.edu.,     Helvetica
  927. °dONLNdˆN¸(#l+___________________________________________
  928. °dONLNd1NÚ*@Only 7-Bit ASCII In NewtonScript Symbols (1/26/94) (Obsoleted by°dONLNdrN(0*!NS Guide 1.0 Final Documentation)
  929. °dONLNdî8NDY*Q:°dONLNdó8`Dfi)TMy frame has some slot symbols that contain accent and special letters. For example:°dONLNdÌPr\‡+=f := {|à|:"help me please", |é|:"Thanks in advance", ...,...}°dONLNd,g`sfi(è~TMy program received a letter from ProtoInputLine and turned it into a symbol. I have°dONLNdÅs`≤* Ntried many different ways to do this but I could not convert it into a symbol.°dONLNd—ãNóY(≥lA:°dONLNd‘ã`ói)=The basic problem is you can only use 7-bit ascii in symbols.
  930. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  931.     °dONLNdˇˇ)Û22ˇ í◊#ˇ ˇˇˇˇ#◊ 
  932. d, Palatino
  933.     .+l+!Newtonscript Programming Language,     Helvetica
  934. °dONLNdˇˇ*7+___________________________________________
  935. °dONLNdGNWÕ*:Nested IF Statements, Constant Condition Problems (6/9/94)
  936. °dONLNd;gNs[*Q: °dONLNd?g`s◊)TI have found a mysterious problem with Scripts containing  nested IFs. In some cases°dONLNdîs`å* @like the following example they are executed in an abnormal way.°dONLNd÷ã`ó‡*XThe true conditions in the real code are constants defined in the project data file with°dONLNd/ó`£j* =values true or nil. These are used for conditional compiling.,
  937. Courier°dONLNdnØrªV+&protoApp.viewSetupDoneScript : FUNC ()°dONLNdñ∫rΔê* begin°dONLNdú≈N—T(Ìl °dONLNdû≈r—∫)$ if TRUE then°dONLNd´–N‹f(¯l    °dONLNd∞–r‹ê)$begin°dONLNd∂€NÁl(l     °dONLNdº€rÁ∫)$ if TRUE then°dONLNd…ÊNÚ~(l        °dONLNd“ÊñÚ¥)Hbegin°dONLNdÿÒN˝Ñ(l             °dONLNd‚Òñ˝fi)H if TRUE then°dONLNdÔ¸N¥($l            begin°dONLNdNú*
  938.              °dONLNd∫)l if TRUE then°dONLNdNÆ(:l                °dONLNd-∫ÿ)lbegin°dONLNd3N)∫(El                  °dONLNdFfi)b)êPrint ("Idlescript1");°dONLNd](N4®(Pl               °dONLNdm(∫4Ã)lend°dONLNdq3N?®([l            end°dONLNdÅ>NJê*         end°dONLNdçINUf*     °dONLNdíIrUä)$end;°dONLNdóTN`Z(|l  °dONLNdöTr`ˆ)$Print ("Idlescript2");°dONLNd≤_rkÑ* end°dONLNd∑v`Çπ(û~OThere should be only two prints. In fact there are five prints in the following°dONLNdÇ`éÑ* manner:°dONLNdôr•¿+
  939. "Idlescript1"°dONLNd §r∞¿*
  940. "Idlescript1"°dONLNd/Ørª¿*
  941. "Idlescript1"°dONLNd>∫rΔ¿*
  942. "Idlescript1"°dONLNdM≈r—¿*
  943. "Idlescript2"°dONLNd\€`Á“(~VIf I define Boolean slots with value truein the base view, and if I use those slots as°dONLNd≥Á`Û„* Vconditions, the code works like it should. Why can nested IFs with constant conditions°dONLNd
  944. Û`ˇØ* work like a loop?°dONLNdN#[(?lA: °dONLNd!`#œ)SThis is a bug in the compiler's handling of IF statements with constant conditions.°dONLNdv#`/∑* PThe bug occurs only if the result of the IF statement is not used.  For example,°dONLNd«:NF¥(bl    func () begin°dONLNdŸENQΔ*         if TRUE then°dONLNdÓPN\fi*             if TRUE then°dONLNd[Ng‰*                 Print(1);°dONLNd!fNr¥*         Print(2);°dONLNd3qN}x*     end°dONLNd<à`îÀ+will trigger the bug, but
  945. °dONLNdˇˇ(≈H=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  946.     °dONLNdˇˇ)Û23ˇ Ï◊#ˇ ˇˇˇˇ#◊ 
  947. d, Palatino
  948.     .+l+!Newtonscript Programming Language,
  949. Courier
  950. °dONLNd5NA¥*2    func () begin°dONLNd@NL*         local x := if TRUE then°dONLNd2KNW * #                       if TRUE then°dONLNdVVNb&* $                           Print(1);°dONLNd{aNm¥*         Print(2);°dONLNdçlNxx*     end°dONLNdñÇ`éá+    will not.°dONLNd°ö`¶*+The workaround is to use the result of the °dONLNdÃö¶.)ºif °dONLNdœö.¶œ)$statement.  You don't really want to°dONLNdÙ¶`≤»(Œ~Okeep the result around, so the above example is not recommended .  The simplest°dONLNdE≤`æ* %workaround is probably the following:°dONLNdk N÷R(Úl  °dONLNdm R÷¨)  func () begin°dONLNd}’N·Ñ(˝l            (°dONLNdá‡NÏfi*             if TRUE then°dONLNd†ÎN˜ˆ*                 if TRUE then°dONLNdΩˆN¸*                     Print(1);°dONLNd€N
  951. ¿*         ) and TRUE;°dONLNdÔ N¥*         Print(2);°dONLNdN#x*     end°dONLNd
  952. .`:fi+RThis works because the NTK 1.0.1 compiler does not throw away the "and true" part,°dONLNd]:`F@* 2but the result of the "if" is dropped immediately.,     Helvetica
  953. °dONLNdë^Np¸(ãl+___________________________________________
  954. °dONLNdΩpNÄ}*,NEW: How to Avoid _parent Problems (6/28/94)
  955. °dONLNdÍåNòY*Q:°dONLNdÌå_òŸ)RI read somewhere that developers should never access a view _parent slot directly?°dONLNd@ò_§s* ?Are there any cases when it is safe to access the _parent slot?°dONLNdÄ∞NºY(ÿlA:°dONLNdÉ∞_ºÿ)SIn most cases, you should use the :Parent() view method to determine a parent view.°dONLNd◊º_»Œ* PHowever, there are some cases when you want to access the _parent slot of a view°dONLNd(»_‘”* Tdirectly.  The situation which is bad is to use _parent as a simple variable because°dONLNd}‘_‡¥* Kresults will vary depending on implementation of the current function. Some°dONLNd…‡_Ïë* guidelines:°dONLNd’ÏN¯~(l        °dONLNdfiÏñ¯fi)H  _parent    °dONLNdÍÏfi¯˘)His bad°dONLNdÒ¯Nfi( l         view:Parent()  °dONLNd    ¯fi¯)êis OK°dONLNdNfi(,l        self._parent    °dONLNd'fi¢)ê+is OK (and should be the same as :Parent())°dONLNdSNfi(8l        view._parent    °dONLNdkfiπ)ê/is OK (and should be the same as view:Parent())
  956. °dONLNdõ@*RÏ(mH-_____________________________________________
  957. °dONLNdˇˇ*X=© Copyright 1993-94 Apple Computer, Inc, All Rights Reserved °dONLNdˇˇ)◊7/7/94
  958.     °dONLNdˇˇ)Û24ˇ